1

我正在使用客户端-服务器编程我指的是这个链接,我的服务器正在成功运行。

  1. 我需要不断地向服务器发送数据。
  2. 我不想每次在发送每个数据包之前都连接()。所以第一次我只是创建了一个套接字并发送第一个数据包,其余的数据我只是使用 write() 函数将数据写入套接字。

但我的问题是,如果服务器不存在或我的以太网被禁用,它仍然成功地将数据写入套接字,则在连续发送数据时。

有没有什么方法可以让我一次创建套接字并在知道服务器故障的情况下连续发送数据?

这样做的主要原因是,在服务器端,我使用的是 GPRS 调制解调器,并且每次为每个数据包调用 connect() 函数时,调制解调器都会挂起。

为了创建套接字,我使用下面的代码

Gprs_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (Gprs_sockfd < 0)
{
  Display("ERROR opening socket");
  return 0;
}
server = gethostbyname((const char*)ip_address);
if (server == NULL)
{               
  Display("ERROR, no such host");                
  return 0;
}

bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(Gprs_sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
  Display("ERROR connecting");
  return 0;
}

每次我使用下面的代码写入套接字时

n = write(Gprs_sockfd,data,length);
if(n<0)
{
  Display("ERROR writing to socket");
  return 0;
}   

提前致谢.............

4

2 回答 2

1

TCP 旨在容忍临时故障。它进行字节排序、确认,并在必要时进行重传。所有未确认的数据都缓存在内核网络堆栈中。如果我没记错的话,默认值是三次重传尝试(如果我错了,请有人纠正我),并带有指数回退超时。这很快就会增加几十秒,如果不是几分钟的话。

我的建议是在你的协议中设计应用程序级别的确认,这意味着服务器会发送一个简短的回复,说它到目前为止收到了这么多数据,比如每秒。如果客户端在 3 秒内没有收到吮吸确认,则客户端知道连接不可用并可以关闭它。顺便说一句,使用非阻塞套接字和轮询函数(如select(2)or )更容易做到这一点poll(2)

编辑0:

我认为这在这里非常相关- “最终的 SO_LINGER 页面,或者:为什么我的 tcp 不可靠”

于 2013-01-10T15:05:45.643 回答
0

Nikolai 在这里是正确的,您在这里遇到的行为是可取的,因为基本上您可以在网络中断后继续传输数据,而无需在应用程序中使用任何逻辑。如果您的应用程序应该检测到超过指定时间的中断,您需要将心跳添加到您的协议中。这是解决问题的标准方法。它还可以让您检测网络正常,接收器还活着,但它已经死锁(由于软件错误)的情况。

心跳可以像 Nikolai 提到的那样简单——每 X 秒发送一个小数据包;如果服务器在 N*X 秒内看不到数据包,则连接将被丢弃。

于 2013-01-11T18:25:27.590 回答