把文件描述符轉標準io FILE 時 (例如: FILE readfp = fdopen(fd,"r") )
若是須要半關閉, 不能使用fclose ,fclose 將直接關閉(close)套接字
仍是須要shutdown 來幫忙 (例如 shutdown(fileno(readfp),SHUT_WR) ) ,先把 FILE* 轉描述符,再調用shutdown;socket
代碼:指針
serv.ccode
int sock = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in serv_addr,cli_addr; memset(&serv_addr,0,sizeof(serv_addr)); memset(&cli_addr,0,sizeof(cli_addr)); serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT); serv_addr.sin_family = AF_INET; socklen_t cli_socklen = sizeof(cli_addr); bind(sock,(SA*)&serv_addr,sizeof(serv_addr)); listen(sock,10); int cli_sock = accept(sock,(SA*)&cli_addr,&cli_socklen); //把套接字轉成標準io FILE* readfp = fdopen(cli_sock,"r"); //讀指針 FILE* writefp = fdopen(cli_sock,"w"); //寫指針 fputs("fuck you 1", writefp); fputs("fuck you 2", writefp); fputs("fuck you 3", writefp); fflush(writefp); // fclose(writefp); 這樣將直接close, 下面的fgets 將收不到數據了 shutdown(fileno(writefp),SHUT_WR); // 仍是使用shutdown 來半關閉 puts("after shutdown"); system("netstat -a | grep 9988"); getchar(); char buf[100] = {0}; if(fgets(buf,100,readfp) == NULL){ puts(" ******** peer closed ********* "); } printf("read : %s\n",buf); fclose(readfp); puts("fclose read"); system("netstat -a | grep 9988");
client.cserver
if(argc !=3){ puts("ip port"); return 0; } int sock = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in serv_addr; memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_port = htons(atoi(argv[2])); serv_addr.sin_addr.s_addr = inet_addr(argv[1]); connect(sock,(SA*)&serv_addr,sizeof(serv_addr)); //把描述符轉成標準io FILE * readfp = fdopen(sock,"r"); FILE* writefp = fdopen(sock,"w"); char buf[100]; while(1){ if(fgets(buf,sizeof(buf),readfp) == NULL){ puts("server closed"); break; } printf("buf:%s\n",buf); fflush(stdout); } fputs("byebye",writefp); fflush(writefp); puts("continue"); getchar(); fclose(writefp); fclose(readfp);