《TCP IP网络编程》第七章 优雅地断开套接字连接

第七章 优雅地断开套接字连接

直接调用close或closesocket函数单方面断开连接,不叫优雅。

7.1 基于TCP的半关闭

单方面断开连接带来的问题

主机A强行close后,由主机B传输的、主机A必须接收的数据也销毁了,所以不优雅。

只关闭一部分数据交换中使用的流的方法就叫优雅的方法。
断开一部分是指:可以传输数据但是无法接收,或可以接收数据但无法传输,就是只关闭流的一半。

套接字和流

两台主机之间有两个流,一个从A到B,一个从B到A,只断开其中的一个流

针对优雅断开的shutdown函数

用于半关闭的函数:

#include<sys/socket.h>
int shutdown(int sock,int howto);
			sock	需要断开的套接字文件描述符
			howto	传递断开方式信息
					SHUT_RD		断开输入流,套接字无法接收数据,即使输入缓冲收到数据也会抹去
					SHUT_WR		断开输出流,套接字无法传输数据。但如果输出缓冲还留有未传输的数据,则将传递至目标主机
					SHUT_RDWR	同时断开I/O流
					
成功返回0,失败返回-1
基于半关闭的文件传输程序

理解传递EOF的重要性和半关闭的重要性:
传递EOF的重要性在于,要告诉客户端,我这边给你发的文件发完啦,别再一直调用输入函数啦;
半关闭的重要性在于,即使通过关闭输出流向文件发送了EOF,也仍然还保留有输入流,这样还是能收到客户端发来的Thank you字符串。

file_server.c:

[root@VM_0_10_centos tcpHalf]# cat 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,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);

        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]));

        bind(serv_sd,(struct sockaddr*)&serv_adr,sizeof(serv_adr));
        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 handling(char * message){
        fputs(message,stderr);
        fputc('\n',stderr);
        exit(1);
}

file_client.c :

[root@VM_0_10_centos tcpHalf]# cat 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);

        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);
        fputc('\n',stderr);
        exit(1);
}

运行结果:

[root@VM_0_10_centos tcpHalf]# ./fserver 9190 &
[1] 5639
[root@VM_0_10_centos tcpHalf]# ./fclient 127.0.0.1 9190
Received file data
Message from client:Thank you 	服务器端半关闭输出流后,表明不往外写东西了,但仍可以接收到客户端发来的信息
[1]+  Done                    ./fserver 9190
[root@VM_0_10_centos tcpHalf]#

7.2 习题

(1)解释TCP中“流”的概念。UDP中能否形成流?请说明原因

TCP的流指:两台主机通过套接字建立连接后进入可交换数据的状态,也称为“流形成的状态”。而对于UDP来说,不存在流,因为两个SOCKET不能相互连接

(2)Linux中的close函数或Windows中的closesocket函数属于单方面断开连接的方法,有可能带来一些问题。什么是单方面断开连接?什么情况下会出现问题?

单方面的断开连接意味着套接字无法再发送数据。一般在对方有剩余数据未发送完成时,断开己方连接,会造成问题。

(3)什么是半关闭?针对输出流执行半关闭的主机处于何种状态?半关闭会导致对方主机接收什么信息?

半关闭是指只关闭输入和输出流中的其中一个。而且,如果对输出流进行半关闭,EOF被传送到对方主机,己方套接字无法再传送别的数据,但可以接收对方主机传送的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值