7.1 优雅断开套接字

来源:互联网 发布:sql server个人版安装 编辑:程序博客网 时间:2024/06/05 12:45

1. 使用close,closesocket函数是单方面断开连接,不够优雅。调用了close意味着完全断开连接,不能发送也不能接收数据。


图中,A发送完数据后断开连接,之后主机再也不发接收B的数据,如此不够优雅。

2. 使用shutdown可以关闭其中的一个流。

#include <sys/socket.h>int shutdown(int sock, int howto);  成功返回0,失败返回-1sock:需要断开的套接字文件描述符howto:断开方式    SHUT_RD:断开输入流    SHUT_WR:断开输出流    SHUT_RDWR:同时断开IO流



3. 基于半关闭的文件传输


file_client.c程序:

#include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <unistd.h>  #include <arpa/inet.h>  #include <sys/socket.h>    #define BUF_SIZE    30    void error_handling(char *message);    int main(int argc, char *argv[]){      int sd;    FILE *fp;      char buf[BUF_SIZE];      int read_cnt;      struct sockaddr_in serv_adr;        if(argc != 3){          printf("Usage : %s <IP> <port>\n",argv[0]);          exit(1);      }          fp = fopen("receive.dat","wb");     sd = socket(PF_INET,SOCK_STREAM,0);      if(sd == -1){          error_handling("socket() error");      }        memset(&serv_adr,0,sizeof(serv_adr));      serv_adr.sin_family=AF_INET;      serv_adr.sin_addr.s_addr=inet_addr(argv[1]);      serv_adr.sin_port=htons(atoi(argv[2]));        connect(sd,(struct sockaddr *)&serv_adr,sizeof(serv_adr));        while((read_cnt = read(sd,buf,BUF_SIZE)) !=0 ){fwrite((void *)buf,1,read_cnt,fp);    }     puts("Received file data");    write(sd,"Thank you",10);    fclose(fp);     close(sd);        return 0;    }    void error_handling(char *message){        fputs(message,stderr);      fputs("\n",stderr);      exit(1);  }  

执行结果:

alex@alex-virtual-machine:/extra/tcpip$ ./client 127.0.0.1 9190Received file dataalex@alex-virtual-machine:/extra/tcpip$ lsa.out          client         host1        server              uecho_server.cbound_host1.c  file_client.c  host2        uecho_client.cbound_host2.c  file_server.c  receive.dat  uecho_con_client.calex@alex-virtual-machine:/extra/tcpip$ cat receive.dat


file_server.c程序:

#include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <unistd.h>  #include <arpa/inet.h>  #include <sys/socket.h>    #define BUF_SIZE    30    void error_handling(char *message);    int main(int argc, char *argv[]){      int serv_sd,clnt_sd;    FILE *fp;      char buf[BUF_SIZE];      int read_cnt;      struct sockaddr_in serv_adr;      struct sockaddr_in clnt_adr;      socklen_t clnt_adr_sz;            if(argc != 2){          printf("Usage : %s <port>\n",argv[0]);          exit(1);      }      fp = fopen("file_server.c","rb");    serv_sd = socket(PF_INET,SOCK_STREAM,0);      if(serv_sd == -1){          error_handling("socket() error");      }        memset(&serv_adr,0,sizeof(serv_adr));      serv_adr.sin_family=AF_INET;      serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);      serv_adr.sin_port=htons(atoi(argv[1]));        if(bind(serv_sd,(struct sockaddr*)&serv_adr,sizeof(serv_adr)) == -1){          error_handling("bind() error");      }        listen(serv_sd,5);        clnt_adr_sz = sizeof(clnt_adr);      clnt_sd = accept(serv_sd,(struct sockaddr *)&clnt_adr,&clnt_adr_sz);    while(1){          read_cnt = fread((void *)buf,1,BUF_SIZE,fp);if(read_cnt<BUF_SIZE){    write(clnt_sd,buf,read_cnt);    break;    }write(clnt_sd,buf,BUF_SIZE);    }        shutdown(clnt_sd,SHUT_WR);    read(clnt_sd,buf,BUF_SIZE);    printf("Message from client:%s \n",buf);    fclose(fp);    close(clnt_sd);     close(serv_sd);    return 0;  }    void error_handling(char *message){        fputs(message,stderr);      fputs("\n",stderr);      exit(1);  }  

执行结果:

alex@alex-virtual-machine:/extra/tcpip$ gcc -o server file_server.calex@alex-virtual-machine:/extra/tcpip$ ./server 9190Message from client:Thank you

0 0
原创粉丝点击