Linux中TCP通信中 send函数 如何判断 何时断开连接了 ??

CCDDzclxy 2013-11-04 09:32:17
RT
我这里主要是想要判断 对方是否断网了。

我说也说不清楚,举个例子,也是我测试的代码和步骤,如下所示。

环境:两台真机(一个Win7,一个XP_sp2)处于同一局域网。Win7上运行虚拟机CentOS_5.8,CentOS_5.8里面运行TCP Client程序;XP里面运行TCP Server程序。

TCP Client代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>//close()
#include<netinet/in.h>//struct sockaddr_in
#include<arpa/inet.h>//inet_ntoa

#include "pthread.h"

#define DEST_PORT 63333
#define DEST_IP_ADDRESS "192.168.2.100"

int g_skt = 0;

void zcPrintTime()
{
time_t lt; /*define a longint time varible*/
lt=time(NULL);/*system time and date*/
struct tm *ptm;
ptm = localtime(<);
printf("%04d-%02d-%02d %02d:%02d:%02d\n",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
}

/*客户端的处理过程*/
void sendInfo(int s)
{
int send_num;
int iSend = 0;

zcPrintTime();
printf("begin send\n");
while(1)
{
char bufScanf[32] = {0};
scanf("%s",bufScanf);

iSend ++;
char send_buf[32] = {0};
sprintf(send_buf, "%d", iSend);
printf("%d will be sent.\n", iSend);
send_num = send(s,send_buf,1,0);
zcPrintTime();
printf("send_num : %d\n", send_num);
if (send_num <= 0)
{
perror("send");
exit(1);
}
else
{
printf("send sucess:%s\n",send_buf);
}
}
}

void* threadRecv(void *p)
{
int recv_num = 0;
printf ("<== threadRecv in\n");
printf("begin recv:\n");
while (1)
{
char recv_buf[1024];
recv_num = recv(g_skt,recv_buf, sizeof(recv_buf), 0);
zcPrintTime();
printf("recv_num : %d\n", recv_num);
if(recv_num <= 0)
{
perror("recv");
//exit(1);
break;
}
else
{
recv_buf[recv_num]='\0';
printf("recv sucess:%s\n",recv_buf);
}
}
printf ("<== threadRecv in\n");
pthread_exit(NULL);
}

int main(int argc,char *argv[])
{
struct sockaddr_in addr_serv;//服务器端地址

g_skt = socket(AF_INET,SOCK_STREAM,0);
if(g_skt < 0)
{
perror("sock");
exit(1);
}
else
{
printf("sock sucessful:\n");
}
memset(&addr_serv,0,sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_port = htons(DEST_PORT);
addr_serv.sin_addr.s_addr = inet_addr(DEST_IP_ADDRESS);
if( connect(g_skt,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr)) < 0){
perror("connect");
printf("connect (%d)\n",errno);
exit(1);
}
else
{
printf("connect sucessful\n");
}

int iErr;
pthread_t thread;
iErr = pthread_create(
&thread,
NULL,
threadRecv,
NULL);
if(iErr != 0)
printf("线程 创建失败");
else
printf("线程 被创建\n");


sendInfo(g_skt);

close(g_skt);
}


测试操作步骤:
1、运行 Tcp Client 连接 Tcp Server。
2、随便输入一个字母+回车(这里输入的是A),于是字符'1'被发送出去。
3、随便输入一个字母+回车(这里输入的是A),于是字符'2'被发送出去。
4、此时,断开 Tcp Server机子上面的网络(禁用网卡)。
5、随便输入一个字母+回车(这里输入的是B),于是字符'3'被发送出去。
6、随便输入一个字母+回车(这里输入的是B),于是字符'4'被发送出去。
7、随便输入一个字母+回车(这里输入的是B),于是字符'5'被发送出去。
8、等了半个多小时,还没有任何错误显示... 于是,又输入字母C+回车,应该是字符'6'被发送出去,还是没有任何错误信息显示出来...

运行结果如下图所示:



问题:
我这里是在发送了 字符'1'、'2'后,自己手动断开了 Tcp Server 的网络,所以知道后面的 '3'、'4'、'5'、'6' 没有发送出去。
但是在实际应用中,我连续发送 字符'1'、'2'、'3'、'4'、'5'、'6',当中如果有对方网络断掉的情况,我如何知道 哪些 字符发送成功了,哪些字符没发送成功??


ps:Linux里面的send函数,和Winsock API send 貌似现象完全不同啊。Win里面非阻塞套接字调用了send,只有在发送成功或超时的情况下才会返回,否则是不会返回的啊,linux里却可以..
ps:到发帖时还是没有任何错误信息输出...


linux 编程菜新手啊,请大家指教啊!! 感谢!!!





...全文
574 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
CCDDzclxy 2013-11-04
  • 打赏
  • 举报
回复
引用 5 楼 max_min_ 的回复:
不要抓断开连接的一方,抓另外一方,
抓的就是Client端的(TCP server 网卡禁用)。
max_min_ 2013-11-04
  • 打赏
  • 举报
回复
引用 4 楼 CCDDzclxy 的回复:
[quote=引用 3 楼 max_min_ 的回复:] 你说的如何判断 字符'1'、'2'、'3'、'4'、'5'、'6', 哪些 字符发送成功了,可以用发送的api来判断! 如果在发送中,对方断开的话,抓包肯定得不到对应的ack确认的,而是得到FIN的! 你api大于0 ,具体发送了多少个呢?和实际对端接受到的数据是否一致呢? 说明在发送 3 4 5 的过程中已经断开了,只是发送端在确认,也就是断开时候的四次握手 6数据根本就没有发送!
我发了1个byte,send返回也是1,'1'、'2'、'3'、'4'、'5'、'6' send的返回值都是1 !!! 我人为的断开了TCP server的网络,所以没有ACK,也没有FIN !!!但是send和recv根本没有异常的信息输出 !!![/quote] 不要抓断开连接的一方,抓另外一方,
CCDDzclxy 2013-11-04
  • 打赏
  • 举报
回复
引用 3 楼 max_min_ 的回复:
你说的如何判断 字符'1'、'2'、'3'、'4'、'5'、'6', 哪些 字符发送成功了,可以用发送的api来判断! 如果在发送中,对方断开的话,抓包肯定得不到对应的ack确认的,而是得到FIN的! 你api大于0 ,具体发送了多少个呢?和实际对端接受到的数据是否一致呢? 说明在发送 3 4 5 的过程中已经断开了,只是发送端在确认,也就是断开时候的四次握手 6数据根本就没有发送!
我发了1个byte,send返回也是1,'1'、'2'、'3'、'4'、'5'、'6' send的返回值都是1 !!! 我人为的断开了TCP server的网络,所以没有ACK,也没有FIN !!!但是send和recv根本没有异常的信息输出 !!!
max_min_ 2013-11-04
  • 打赏
  • 举报
回复
心跳是来判断长连接的! 你说的如何判断 字符'1'、'2'、'3'、'4'、'5'、'6', 哪些 字符发送成功了,可以用发送的api来判断! 如果在发送中,对方断开的话,抓包肯定得不到对应的ack确认的,而是得到FIN的! 你api大于0 ,具体发送了多少个呢?和实际对端接受到的数据是否一致呢? 说明在发送 3 4 5 的过程中已经断开了,只是发送端在确认,也就是断开时候的四次握手 6数据根本就没有发送!
CCDDzclxy 2013-11-04
  • 打赏
  • 举报
回复
引用 1 楼 max_min_ 的回复:
1 确认链路是否连通状态,最好加心跳机制, 如果一定时间没有收到心跳包,或者没有回复心跳 就应认为此链路已经坏掉了,需要关闭,重新连接!
“链路是否连通”什么意思??我现在是在连续发数据的时候对方中断,还要靠心跳机制??就算用心跳,在我的问题里面也没用啊,心跳能判断是否断开了,但是如何判断 字符'1'、'2'、'3'、'4'、'5'、'6', 哪些 字符发送成功了,哪些字符没发送成功??
引用 1 楼 max_min_ 的回复:
2 至于发送数据,应该检查对应的api的返回值,是否已经成功发送或者接受定长数据! 没有完成应该重新发送或者接受
我这个测试代码里面,send的返回值一直都是 >0 的啊(打印的 send_num 的值)。
引用 1 楼 max_min_ 的回复:
3 网络数据问题,可以用抓包工具直接抓包看数据,可以看的比较透彻 工具 Linux下用tcpdump,windows用wirekshark
抓包,我刚也抓了,字符'1'、'2'传出去了,有ACK返回,字符'3'、'4'、'5'在重传,字符'6'根本没有这条数据包...
max_min_ 2013-11-04
  • 打赏
  • 举报
回复
1 确认链路是否连通状态,最好加心跳机制, 如果一定时间没有收到心跳包,或者没有回复心跳 就应认为此链路已经坏掉了,需要关闭,重新连接! 2 至于发送数据,应该检查对应的api的返回值,是否已经成功发送或者接受定长数据! 没有完成应该重新发送或者接受 3 网络数据问题,可以用抓包工具直接抓包看数据,可以看的比较透彻 工具 Linux下用tcpdump,windows用wirekshark

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧