我正在使用客户端 - 服务器编程我引用此link并且我的服务器已成功运行。
但我的问题是在服务器不存在或者我的以太网被禁用的情况下连续发送数据时仍然成功地将数据写入套接字。
我是否有任何方法可以一次创建套接字并在知道服务器故障的情况下连续发送数据?
这样做的主要原因是,在服务器端我使用GPRS调制解调器,并且每次调用connect()函数时,每个数据包都会被调制解调器挂起。
使用以下代码创建套接字I
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;
}
提前致谢.............
答案 0 :(得分:1)
TCP旨在容忍临时故障。它执行字节排序,确认以及必要时的重传。所有未确认的数据都缓存在内核网络堆栈中。如果我没记错的话,默认是三次重新传输尝试(有人纠正我,如果我错了)指数退避超时。如果不是几分钟,这很快就会增加几十秒。
我的建议是将应用程序级确认设计到您的协议中,这意味着服务器会发送一个简短的回复,说它到目前为止收到了那么多数据,比如每秒钟。如果客户端在3秒内没有收到suck ack,则客户端知道连接不可用并且可以关闭它。顺便说一句,使用非阻塞套接字和轮询函数(如select(2)
或poll(2)
)可以更轻松地完成此任务。
我认为这在这里非常重要 - "The ultimate SO_LINGER page, or: why is my tcp not reliable"。
答案 1 :(得分:0)
Nikolai在这里是正确的,你在这里遇到的行为是可取的,因为基本上你可以在网络中断后继续传输数据,而你的应用程序中没有任何逻辑。如果您的应用程序应检测到超过指定时间的中断,则需要在协议中添加 heartbeating 。这是解决问题的标准方法。当网络可以正常,接收器处于活动状态时,它还可以允许您检测情况,但它已经死锁(由于软件错误)。
心跳可以像尼古拉提到的一样简单 - 每隔X秒发送一个小包;如果服务器在N * X秒内看不到数据包,则连接将被丢弃。