把文件描述符转标准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);