socket 建立连接与三次握手的对应关系
2017-08-04 11:44
423 查看
Socket 与 TCP 协议
socket 用于网络编程,通过 TCP/UDP 协议建立通信。而面试中也常常问及 Socket 和三次握手的对应关系。一般人都认为是这样的关系。(最初也是这样设计的)connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
SYN Flood 攻击
但是实际上,出于安全考虑,为了避免太过容易的 SYN Flood 攻击 ,客户端仅仅发出大量的 socket 连接请求,而服务器需要分配太多的 socket ,导致资源耗尽 。实际上在 accept() 函数之前,已经完成了三次握手过程,这在一定程度上可以减少 SYN Flood 攻击。
实验测试
通过模拟 socket 建立连接的代码(代码在文末),模拟了简单的 socket 连接过程,同时启动 wireshark ,进行抓包,设置过滤规则 tcp.port = 7000 。这里先在服务器端的 accept () 函数之前,增加了 while(1){}; 死循环,即不执行 accept() 函数。
在启动服务器和客户端后,抓取到的报文如下,可以看到,已经完成了三次握手。
在关闭客户端 socket 之后,仅仅进行了两次握手,因为服务端并没有执行 accept 函数分配 socket.
socket 通信代码
//服务器端代码 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <thread> #include <iostream> #define PORT 7000 #define QUEUE 20 int conn; void thread_task() { } int main() { //printf("%d\n",AF_INET); //printf("%d\n",SOCK_STREAM); int ss = socket(AF_INET, SOCK_STREAM, 0); //printf("%d\n",ss); struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); //printf("%d\n",INADDR_ANY); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } if(listen(ss, QUEUE) == -1) { perror("listen"); exit(1); } struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); ///成功返回非负描述字,出错返回-1 while(1){}; // 不执行后面语句,仅仅监听客户端连接而不分配 socket conn = accept(ss, (struct sockaddr*)&client_addr, &length); if( conn < 0 ) { perror("connect"); exit(1); } char buffer[1024]; //创建另外一个线程 //std::thread t(thread_task); //t.join(); //char buf[1024]; //主线程 while(1) { // memset(buf, 0 ,sizeof(buf)); // if(fgets(buf, sizeof(buf),stdin) != NULL) { // send(conn, buf, sizeof(buf), 0); // } memset(buffer, 0 ,sizeof(buffer)); int len = recv(conn, buffer, sizeof(buffer), 0); if(strcmp(buffer, "exit\n") == 0) break; printf("%s", buffer); //必须要有返回数据, 这样才算一个完整的请求 send(conn, buffer, len , 0); } close(conn); close(ss); return 0; }
// 客户端 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 7000 #define BUFFER_SIZE 1024 int main() { ///定义so int sock_cli = socket(AF_INET,SOCK_STREAM, 0); printf("%d\n",sock_cli); ///定义sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服务器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送 if(strcmp(sendbuf,"exit\n")==0) break; recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收 fputs(recvbuf, stdout); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(sock_cli); return 0; }
相关文章推荐
- Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
- UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认
- UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- tcp 三次握手和四次断连深入分析:连接状态和socket API的关系
- UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认
- (转)Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
- TCP连接的三次握手和Socket建立网络连接的步骤
- TCP与SOCKET的三次握手的对应关系
- Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- tcp 三次握手和四次断连深入分析:连接状态和socket API的关系----BAT 李运华
- tcp 三次握手和四次断连深入分析:连接状态和socket API的关系
- socket中TCP的三次握手建立连接详解
- TCP连接的建立与终止,三次握手和四次握手,以及在socket系列函数中的体现
- tcp 三次握手和四次断连深入分析:连接状态和socket API的关系
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- SOCKET API和TCP STATE的对应关系_三次握手(listen,accept,connect)_四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUICK
- Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
- tcp 三次握手和四次断连深入分析:连接状态和socket API的关系