"TCP/IP Network Programming" reading notes--half-closed based on TCP

Table of contents

1--TCP-based half-close

1-1--The problem of TCP unilateral complete disconnection

1-2--shutdown() function

1-3--Necessity of semi-closed

2--Semi-closed file transfer program


1--TCP-based half-close

1-1--The problem of TCP unilateral complete disconnection

        The close function in the Linux system will completely disconnect the TCP Socket connection, which means that data cannot be sent and received (input stream and output stream are closed), which may cause host A to be unable to receive data from host B (input stream of host A stream is closed); 

1-2--shutdown() function

#include <sys/socket.h>
int shutdown(int sock, int howto);
// 成功时返回 0, 失败时返回 -1
// sock 表示需要断开的 Socket 的文件描述符
// howto 表示传递断开的方式信息

        The shutdown() function can avoid the problem of data loss caused by complete shutdown above, and it selectively disconnects the input stream and output stream by specifying the disconnection method ;

        The disconnection method is specified by the second parameter, where SHUT_RD means disconnecting the input stream , SHUT_WR means disconnecting the output stream , and SHUT_RDWR means disconnecting the I/O stream at the same time ;

1-3--Necessity of semi-closed

        For server-side/client-side data transmission problems, the server side that transfers files only needs to continuously transmit file data, but the client side cannot know when to end receiving data;

        In order to solve the above problems, the server should send an EOF to the client to indicate the end of file transfer , and the client can stop receiving data by knowing the end of file transfer by receiving EOF ;

        Disconnecting the output stream can pass EOF outward (whether setting SHUT_WR or using the close() function directly);

2--Semi-closed file transfer program

Service-Terminal:

// gcc file_server.c -o file_server
// ./file_server 9190

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

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;

}

client:

// gcc file_client.c -o file_client
// ./file_client 127.0.0.1 9190

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

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;
}

operation result:

Guess you like

Origin blog.csdn.net/weixin_43863869/article/details/132719338