linux accept函数与三次握手没有半毛钱的关系------三次握手可能发生在调用accept函数之前
2017-07-26 23:34
323 查看
想必大家对tcp三次握手已经乱熟于心了, 在很多地方, 描述三次握手的时候, 总把accept函数扯进去, 其实三次握手和accept函数没有半毛钱的关系。 在linux中, accept函数的作用是: 从已经完成连接的socket队列中取出一个socket, 如果没有已经完成连接的socket, 那么accepte函数就会阻塞。 所以, 三次握手可以发生在accept函数调用之前, 来看看吧。
服务端程序为:
启动它, 可以看到, 在accept之前, 有getchar()阻塞, 我们让它阻塞, 不执行accept.
客户端程序为:
我们启动3个客户端, 从客户端的结果可以看到, connect函数返回了, 且都是0, 而且, 在服务端也可以看到3个ESTABLISHED状态的socket, 而且, 如果用tcpdump抓包, 还能看到9次握手的过程。 这充分说明, 在调用accept函数之前, 已经完成了完整的握手。
到这里, 大家应该对accept函数有更清晰的认识了。
建议大家试试上面的程序, 反正我已经试过了, 有点意思。
服务端程序为:
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> int main() { sockaddr_in servAddr; memset(&servAddr,0,sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = INADDR_ANY; servAddr.sin_port = htons(8765); int iListenSocket = socket(AF_INET, SOCK_STREAM, 0); bind(iListenSocket, (sockaddr *)&servAddr, sizeof(servAddr)); listen(iListenSocket,5); int i = 0; while(1) { sockaddr_in clientAddr; socklen_t iSize = sizeof(clientAddr); memset(&clientAddr, 0, sizeof(clientAddr)); getchar(); // 卡住 int iConnSocket = accept(iListenSocket,(sockaddr*)&clientAddr, &iSize); if(iConnSocket < 0) { if(errno == EINTR || errno == ECONNABORTED) { continue; } else { printf("accept error, server\n"); return -1; } } char szBuf[1024] = {0}; snprintf(szBuf, sizeof(szBuf), "client ip[%s], index %d", inet_ntoa(clientAddr.sin_addr), ++i); write(iConnSocket, szBuf, strlen(szBuf) + 1); getchar(); // 卡住 close(iConnSocket); } getchar(); close(iListenSocket); return 0; }
启动它, 可以看到, 在accept之前, 有getchar()阻塞, 我们让它阻塞, 不执行accept.
客户端程序为:
#include <unistd.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> int main() { int sockClient = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8765); int iRet = connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); printf("connect iRet: %d\n", iRet); char szBuf[2048] = {0}; iRet = recv(sockClient, szBuf, sizeof(szBuf) - 1 , 0); printf("msg from server: %s\n", szBuf); getchar(); close(sockClient); return 0; }
我们启动3个客户端, 从客户端的结果可以看到, connect函数返回了, 且都是0, 而且, 在服务端也可以看到3个ESTABLISHED状态的socket, 而且, 如果用tcpdump抓包, 还能看到9次握手的过程。 这充分说明, 在调用accept函数之前, 已经完成了完整的握手。
到这里, 大家应该对accept函数有更清晰的认识了。
建议大家试试上面的程序, 反正我已经试过了, 有点意思。
相关文章推荐
- SOCKET API和TCP STATE的对应关系_三次握手(listen,accept,connect)_四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUICK
- SOCKET API和TCP STATE的对应关系_三次握手(listen,accept,connect)_四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUICK
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- 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 API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUI
- linux内核中,tcp连接三次握手过程中的,tcp协议栈中的函数调用关系
- tcp连接三次握手过程中的,tcp协议栈中的函数调用关系
- tcp三次握手的过程,accept发生在三次握手哪个阶段?
- tcp三次握手的过程,accept发生在三次握手哪个阶段?
- 函数传对象调用,为什么值没有发生变化?
- Socket 之accept与三次握手的关系
- tcp三次握手的过程,accept发生在三次握手哪个阶段?
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认
- 三次握手与accept()函数