今天學習過程中發現了自己編寫的服務器多次運行后,該端口的網絡狀態變成close_wait,導致服務器無法使用該端口。
首先,要理解出現的步驟,
在TCP狀態圖中,當服務器接收到對端的關閉FIN請求后返回ACK確認請求然后服務端進入close_wait,當長時間
處於close_wait狀態,說明服務端並未主動進行關閉。主要問題就是你的代碼並未正確處理主動關閉連接。可能是程序
正處於讀寫,而在讀寫結束后又未正確的進行close連接,導致未能進入last_ack狀態。
綜上所述,是代碼中close的問題。
//貼一個簡單的echo服務器
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #define PORT 10002 int main(){ //緩存區 char buf[BUFSIZ]; int listenfd; int port = PORT; listenfd = socket(AF_INET, SOCK_STREAM, 0); //消除bind "address already in use" int flag = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); struct sockaddr_in server_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons((unsigned int)port); if(bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){ return -1; } listen(listenfd, 1024); struct sockaddr_in client; memset(&client, 0, sizeof(client)); socklen_t client_len = sizeof(client); int accept_fd = 0; accept_fd = accept(listenfd, (struct sockaddr*)&client, &client_len); if(accept_fd < 0){ printf("errno is %d\n", errno); } else{ printf("ip : %s", inet_ntoa(client.sin_addr)); printf("port: %d", ntohs(client.sin_port)); int pipefd[2]; if(pipe(pipefd) == -1){ perror("pipe errno! \n"); } ssize_t ret = splice(accept_fd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE); if((ret) == -1){ perror("splice errno! \n"); } ssize_t ret1 = splice(pipefd[0], NULL, accept_fd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE); if((ret1) == -1){ perror("splice errno! \n"); } } close(accept_fd); close(listenfd); return 0; }