Linux下的TCP/IP编程------基于TCP的半关闭

原创 2016年05月31日 11:27:03

在TCP服务端和客户端建立连接之后服务端和客户端会分别有两个独立的输入流和输出流,而且相互对应。服务端的输出流对应于客户端的输入流,服务端的输入流对应于客户端的输出流。这是在建立连接之后的状态。

当我们调用close()函数时,系统会同时把双方的输入流和输出流全部关闭,但是有时候我们仍需要在一方断开连接之后只进行接受数据或者传输数据其中一项操作。这时就需要我们只断开输入或者输出,保留另一个流的正常运转,也就引入了TCP的半关闭状态。

基本操作:

之前我们传输完数据之后便直接调用了close()函数,我们可以使用系统提供的shutdown()函数方便的完成TCP的半关闭。

shutdown(int socket , int type):半关闭套接字中的输入或者输出流

  • socket(套接字描述符):需要断开的套接字描述符

  • type(断开类型):套接字的断开方式

    SHUT_RD——断开输入流,并清空输入缓冲中的数据

    SHUT_WR——断开输出流,并将输出缓冲中的数据输出

    SHUT_RDWR——同时断开输入输出流,分两次调用shutdown()函数

成功时返回0,失败时返回-1

服务端:

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>

#define BUFF_SIZE 30

void error_handling(char *message);

/**
基于TCP的半连接服务端
**/
int mainn(int argc ,char *argv[]){
    //客户端和服务端的socket描述符
    int  serv_sock;
    int clent_sock;
    //客户端和服务端的地址
    struct sockaddr_in serv_addr;
    struct sockaddr_in clent_addr;
    //客户端地址大小
    socklen_t  client_addr_size;
    //用于记录读取的文件字节数
    int read_count;
    //缓冲大小
    char buff[BUFF_SIZE];
    //用于打开文件的文件指针
    FILE *fp;
    //检查输入的参数个数是否合法
    if(argc!=2){
        printf("Usage : %s  <port> \n ",argv[0]);
        exit(1);
    }

    //使用文件描述符打开文件
    fp = fopen("word_file.txt","rb");
    //创建服务端saocket
    serv_sock = socket(AF_INET,SOCK_STREAM,0);
    //将server_addr中的内容清空
    memset(&serv_addr,0,sizeof(serv_addr));
    //初始化socket地址
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(atoi(argv[1]));

    //进行地址绑定
    if(bind(serv_sock,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) == -1){
        error_handling("bind() error");
    }
    //使服务端进入监听状态
    if(listen(serv_sock,5) == -1){
        error_handling("listen() error");
    }
    //获的客户端地址的大小
    client_addr_size = sizeof(clent_addr);
    clent_sock = accept(serv_sock,(struct sockaddr *) &clent_addr,&client_addr_size);

    while(1){
        //读取的文件字节数
        read_count = fread((void *) buff,1,BUFF_SIZE,fp);
        //向客户端写入数据
        if(read_count<BUFF_SIZE){
            write(clent_sock,buff,read_count);
            break;
        }
        write(clent_sock,buff,BUFF_SIZE);
    }
    /**
    在数据输出完成之后,对输出流进行流半关闭
    这种状态下服务读不能向客户端写入数据,但是可以接受来自客户端的数据
    **/
    shutdown(clent_sock,SHUT_WR);
    //接受来自客户端的消息
    read(clent_sock,buff,BUFF_SIZE);
    //打印消息
    printf("Message from client : %s \n",buff);
    //关闭文件
    fclose(fp);
    //彻底关闭TCP连接
    close(clent_sock);
    close(serv_sock);

return 0;

}



void error_handling(char * message){
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>

#define BUFF_SIZE 30

void error_handling(char *message);


int main(int argc ,char *argv[]){
    int sock;
    FILE *fp;

    char buff[BUFF_SIZE];
    int read_count;
    struct sockaddr_in server_addr;

    if(argc!=3){
        printf("Usage : %s  <port> \n ",argv[0]);
        exit(1);
    }

    fp = fopen("recevice.dat","wb");
    sock = socket(AF_INET,SOCK_STREAM,0);

    memset(&server_addr,0,sizeof(server_addr));

    //初始化socket地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    server_addr.sin_port = htons(atoi(argv[2]));

    connect(sock,(struct sockaddr *) &server_addr,sizeof(server_addr));

    while(read_count = read(sock,buff,BUFF_SIZE) != 0){
        //向文件中写入读取到的数据
        fwrite((void *) buff,1,read_count,fp);
    }
    //打印接收到的数据
    puts("Recevied file data");
    //接收完成之后向服务端发送一个消息
    write(sock,"Thank you ",10);

    //关闭文件和socket连接
    fclose(fp);
    close(sock);
    return 0;
}

void error_handling(char * message){
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

至此就完成了一个基于半关闭的TCP服务端/客户端程序,这样使得服务端在传输完数据之后可以只保留输入流,关闭输出流。

版权声明:本文为博主原创文章,转载请注明出处。

基于TCP的半关闭

windows的closesocket函数意味着完全断开连接(单方面断开连接)。完全断开不仅指无法传输数据,而且也不能接受数据。因此,在某些情况下closesocket函数断开连接就显得不太适用。 ...
  • zl908760230
  • zl908760230
  • 2017年04月19日 15:23
  • 258

深入浅出TCP之半关闭与CLOSE_WAIT

终止一个连接要经过4次握手。这由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递,可理解为两个方向相反的独立通道),因此每个方向必须单独地进行关闭...
  • realmeh
  • realmeh
  • 2014年01月13日 23:32
  • 3466

基于TCP的半关闭

基于TCP的半关闭 TCP练级的半关闭简而言之就是”关闭连接的一半”(只可以传递或接收数据)   套接字和流 两台主机通过套接字建立连接后进入可交换数据的状态(流形参的状态),即将建立套接字后可交换数...
  • Hello_World_LVLcoder
  • Hello_World_LVLcoder
  • 2016年12月22日 07:17
  • 583

半连接、半打开、半关闭

一、半连接 1.1 定义       发生在TCP3次握手中。       如果A向B发起TCP请求,B也按照正常情况进行响应了,但是A不进行第3次握手,这就是半连接。 1.2 半连接攻击      ...
  • kanguolaikanguolaik
  • kanguolaikanguolaik
  • 2013年09月17日 11:47
  • 4252

TCP半关闭

关闭TCP连接       http://book.51cto.com/art/200902/109775.htm TCP/IP学习笔记(六)       http://www.qqread.co...
  • zxg519
  • zxg519
  • 2014年01月15日 12:06
  • 718

linux不重启服务的情况下关闭某条链路的tcp连接

linux不重启服务的情况下断开某一条链路的tcp连接 (tcp_drop)采用本方法,在linux中不需要重启系统服务,就可以把外部的某条ip的tcp连接断开(Suse 11 SP3 亲测)...
  • fox_hacker
  • fox_hacker
  • 2016年11月10日 14:41
  • 2100

Linux下socket TCP的简单例子

2011年2月22日 源代码:已经上传至我的资源 服务器端: #include #include // for close function #include // for bzer...
  • pafone
  • pafone
  • 2011年02月22日 10:06
  • 9668

Linux下tcp通信程序

  • 2012年12月08日 11:29
  • 2KB
  • 下载

Linux下的TCP/IP编程----基础篇

Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。 Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取...
  • wqc_CSDN
  • wqc_CSDN
  • 2016年05月26日 21:34
  • 1827

linux下TCP通信简单实例

基于TCP(面向连接)的socket编程,分为客户端和服务器端。 服务器端的流程如下: (1)创建套接字(socket) (2)将套接字绑定到一个本地地址和端口上(bind) (3)将套接字设为监听...
  • rosekin
  • rosekin
  • 2014年01月27日 14:56
  • 9788
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux下的TCP/IP编程------基于TCP的半关闭
举报原因:
原因补充:

(最多只允许输入30个字)