如何在C中检查服务器端是否build立连接

我已经写了下面的代码在服务器端的聊天客户端使用C.但是,在while循环内,我需要检查客户端是否退出程序,即是否与客户端的连接丢失。 请告诉我如何写这样的代码。

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <time.h> int main() { int sock, connected, bytes_recieved , true = 1, pid; char send_data [1024] , recv_data[1024]; struct sockaddr_in server_addr,client_addr; int sin_size; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Socket"); exit(1); } if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) { perror("Setsockopt"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(3128); server_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(server_addr.sin_zero),8); if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { perror("Unable to bind"); exit(1); } if (listen(sock, 5) == -1) { perror("Listen"); exit(1); } printf("\nTCPServer Waiting for client on port 3128"); fflush(stdout); FILE *log; log = fopen("time.log", "a"); time_t t; while(1) { sin_size = sizeof(struct sockaddr_in); connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); printf("\n I got a connection from (%s , %d)", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); fflush(stdout); int pid=fork(); while(1) { if(pid == 0) { usleep(1000000); time(&t); send(connected, ctime(&t),30, 0); } else { bytes_recieved = recv(connected,recv_data,1024,0); recv_data[bytes_recieved] = '\0'; fputs(recv_data, log); fputs("Time: ", log); time(&t); fputs(ctime(&t), log); } fflush(log); } } fclose(log); close(sock); return 0; } 

请帮忙。

现在我修改了这样的代码:

 while(1) { if(pid == 0) { usleep(1000000); time(&t); send(connected, ctime(&t),30, 0); } else { bytes_recieved = recv(connected,recv_data,1024,0); recv_data[bytes_recieved] = '\0'; fputs(recv_data, log); fputs("Time: ", log); time(&t); fputs(ctime(&t), log); } fflush(stdout); fflush(log); fclose(log); if(bytes_recieved == 0 || bytes_recieved == -1) { close(sock); goto connct;} } } close(sock); return 0; 

编译时,它会很好,但在运行时,它会给出以下错误输出:

 *** glibc detected *** ./server: double free or corruption (!prev): 0x09936008 *** ======= Backtrace: ========= /lib/i686/cmov/libc.so.6(+0x6b381)[0xb7659381] /lib/i686/cmov/libc.so.6(+0x6cbd8)[0xb765abd8] /lib/i686/cmov/libc.so.6(cfree+0x6d)[0xb765dcbd] /lib/i686/cmov/libc.so.6(fclose+0x14a)[0xb764982a] ./server[0x8048c21] /lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb7604ca6] ./server[0x8048861] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 08:01 133298 /home/harikrishnan/server/server 08049000-0804a000 rw-p 00000000 08:01 133298 /home/harikrishnan/server/server 09936000-09957000 rw-p 00000000 00:00 0 [heap] b7400000-b7421000 rw-p 00000000 00:00 0 b7421000-b7500000 ---p 00000000 00:00 0 b75bf000-b75dc000 r-xp 00000000 08:01 3653635 /lib/libgcc_s.so.1 b75dc000-b75dd000 rw-p 0001c000 08:01 3653635 /lib/libgcc_s.so.1 b75ed000-b75ee000 rw-p 00000000 00:00 0 b75ee000-b772e000 r-xp 00000000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b772e000-b772f000 ---p 00140000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b772f000-b7731000 r--p 00140000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b7731000-b7732000 rw-p 00142000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b7732000-b7735000 rw-p 00000000 00:00 0 b7744000-b7747000 rw-p 00000000 00:00 0 b7747000-b7748000 r-xp 00000000 00:00 0 [vdso] b7748000-b7763000 r-xp 00000000 08:01 3654097 /lib/ld-2.11.3.so b7763000-b7764000 r--p 0001b000 08:01 3654097 /lib/ld-2.11.3.so b7764000-b7765000 rw-p 0001c000 08:01 3654097 /lib/ld-2.11.3.so bfd94000-bfda9000 rw-p 00000000 00:00 0 [stack] *** glibc detected *** ./server: double free or corruption (!prev): 0x09936008 *** ======= Backtrace: ========= /lib/i686/cmov/libc.so.6(+0x6b381)[0xb7659381] /lib/i686/cmov/libc.so.6(+0x6cbd8)[0xb765abd8] /lib/i686/cmov/libc.so.6(cfree+0x6d)[0xb765dcbd] /lib/i686/cmov/libc.so.6(fclose+0x14a)[0xb764982a] ./server[0x8048c21] /lib/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb7604ca6] ./server[0x8048861] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 08:01 133298 /home/harikrishnan/server/server 08049000-0804a000 rw-p 00000000 08:01 133298 /home/harikrishnan/server/server 09936000-09957000 rw-p 00000000 00:00 0 [heap] b7400000-b7421000 rw-p 00000000 00:00 0 b7421000-b7500000 ---p 00000000 00:00 0 b75bf000-b75dc000 r-xp 00000000 08:01 3653635 /lib/libgcc_s.so.1 b75dc000-b75dd000 rw-p 0001c000 08:01 3653635 /lib/libgcc_s.so.1 b75ed000-b75ee000 rw-p 00000000 00:00 0 b75ee000-b772e000 r-xp 00000000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b772e000-b772f000 ---p 00140000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b772f000-b7731000 r--p 00140000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b7731000-b7732000 rw-p 00142000 08:01 3670051 /lib/i686/cmov/libc-2.11.3.so b7732000-b7735000 rw-p 00000000 00:00 0 b7744000-b7747000 rw-p 00000000 00:00 0 b7747000-b7748000 r-xp 00000000 00:00 0 [vdso] b7748000-b7763000 r-xp 00000000 08:01 3654097 /lib/ld-2.11.3.so b7763000-b7764000 r--p 0001b000 08:01 3654097 /lib/ld-2.11.3.so b7764000-b7765000 rw-p 0001c000 08:01 3654097 /lib/ld-2.11.3.so bfd94000-bfda9000 rw-p 00000000 00:00 0 [stack] Aborted 

任何想法是什么实际问题是?

如果发送返回SOCKET_ERROR,表示套接字已关闭或连接丢失

所以就这样做

 if (send(connected, ctime(&t),30, 0) == SOCKET_ERROR) { // blablabla } 

一旦客户端关闭连接, recv()将返回0 。 如果在尝试从套接字获取数据时出现任何错误,则返回-1

请参阅手册页获取更多信息。

所以改变你的代码

  int conn_closed = 0; bytes_recieved = recv(connected,recv_data,1024,0); switch (bytes_recieved) { case 0: /* connection closed by client */ close(connected); conn_closed = 1; break; case -1: /* error on socket */ /* TODO: insert error handling code */ if (errno == EAGAIN || errno == EINTR) { /* safe to retry */ conn_closed = 0; } else { close(connected) conn_closed = 1; } break; default: recv_data[bytes_recieved] = '\0'; fputs(recv_data, log); fputs("Time: ", log); time(&t); fputs(ctime(&t), log); conn_closed = 0; break; } /* break out of the loop if conn_closed */ if (conn_closed) break; 

并且不要忘记检查send()的返回值,以查看发送数据时是否发生错误。

更新:为EAGAINEINTR添加错误处理代码。

第二次更新:

为了完整性,这里是你应该添加发送的代码

 if (send(connected, ctime(&t),30, 0) == -1) { if (errno == EAGAIN || errno == EINTR) { /* retry to send */ } close(connected); break; } 

在你的情况一个小建议,而不是给出一个'如果'的条件来检查连接,在“while”,而不是“while(1)”内做同样的条件。