网络编程Socket之RST详解
Posted sunbines
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程Socket之RST详解相关的知识,希望对你有一定的参考价值。
网络编程Socket之RST详解
产生RST的三个条件:
- 目的地为某端口的SYN到达,然而该端口上没有正在监听的服务器;
- TCP想取消一个已有的连接;
- TCP接收到一个根本不存在的连接上的分节;
现在模拟上面的三种情况:
client:
1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <netinet/in.h> 5 #include <arpa/inet.h> 6 #include <errno.h> 7 8 #define SERV_PORT 8000 9 10 int main() 11 12 struct sockaddr_in serverAdd; 13 bzero(&serverAdd, sizeof(serverAdd)); 14 serverAdd.sin_family = AF_INET; 15 inet_pton(AF_INET, "127.0.0.1", &serverAdd.sin_addr.s_addr); 16 serverAdd.sin_port = htons(SERV_PORT); 17 int connfd = socket(AF_INET, SOCK_STREAM, 0); 18 19 int connResult = connect(connfd, (struct sockaddr*) & serverAdd, sizeof(serverAdd)); 20 if (connResult < 0) 21 22 printf("连接失败\\n"); 23 close(connfd); 24 return; 25 26 ssize_t writeLen; 27 char sendMsg[5000] = 0 ; 28 unsigned long long totalSize = 0; 29 while (1) 30 31 writeLen = write(connfd, sendMsg, sizeof(sendMsg)); 32 if (writeLen < 0) 33 34 printf("发送失败"); 35 return 0; 36 37 else 38 39 totalSize += writeLen; 40 printf("发送成功 totalSize = %zd\\n", totalSize); 41 42 43
service:
1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <netinet/in.h> 5 #include <arpa/inet.h> 6 7 #define SERV_PORT 8000 8 9 int main(int argc, const char * argv[]) 10 11 12 struct sockaddr_in serverAdd; 13 struct sockaddr_in clientAdd; 14 15 bzero(&serverAdd, sizeof(serverAdd)); 16 serverAdd.sin_family = AF_INET; 17 serverAdd.sin_addr.s_addr = htonl(INADDR_ANY); 18 serverAdd.sin_port = htons(SERV_PORT); 19 20 socklen_t clientAddrLen; 21 22 int listenfd = socket(AF_INET, SOCK_STREAM, 0); 23 int yes = 1; 24 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); 25 26 if (listenfd < 0) 27 28 printf("创建socket失败\\n"); 29 return -1; 30 31 32 int bindResult = bind(listenfd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)); 33 if (bindResult < 0) 34 35 printf("绑定端口失败\\n"); 36 close(listenfd); 37 return -1; 38 39 40 listen(listenfd, 20); 41 42 int connfd; 43 unsigned char recvMsg[246988]; 44 unsigned long long totalSize = 0; 45 46 clientAddrLen = sizeof(clientAdd); 47 connfd = accept(listenfd,(struct sockaddr *)&clientAdd,&clientAddrLen); 48 if (connfd < 0) 49 50 printf("连接失败\\n"); 51 return -1; 52 53 else 54 55 // 这里我们用于测试,只接收一个连接 56 close(listenfd); 57 58 close(connfd); 59 return 0; 60
情况一:
不运行服务端,直接运行客户端程序:
客户端打印信息:
情况二:
运行服务端,再运行客户端程序:
连接失败
假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client,此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。
当一个进程向某个已收到RST的套接字执行写操作时,(此时写操作返回EPIPE错误)内核向该进程发送一个SIGPIPE信号,该信号的默认行为是终止进程,因此进程必须捕获它以免不情愿地被终止;
以上是关于网络编程Socket之RST详解的主要内容,如果未能解决你的问题,请参考以下文章