《TCP/IP网络编程》--基于TCP实现字符串对话和文件传输

1--基于TCP实现字符串对话

主要需求:

服务器端和客户端各传递 1 次字符串,基于 TCP 协议,传递字符串前先以 4 字节整数型方式传递字符串长度,剩余部分为字符串数据;

注:下面的代码基于 Windows 系统实现;

1-1--服务器端

cpp 复制代码
// gcc string_server_win.c -o string_server_win -lwsock32
// string_server_win 9190

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#define BUF_SIZE 1024
#define Len_SIZE 4

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

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

    WSADATA wsaData; // init Socket lib
    if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ 
        ErrorHandling("WSAStartup() error!");
    }

    int Serv_sock = socket(PF_INET, SOCK_STREAM, 0); // create socket
    if (Serv_sock == -1) {
        ErrorHandling("socket() error");
    }

    struct sockaddr_in serv_addr; // allocate ip, port
    memset(&serv_addr, 0, sizeof(serv_addr)); 
    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){ 
        ErrorHandling("bind() error");
    }

    if (listen(Serv_sock, 5) == -1) { // ready
        ErrorHandling("listen() error");
    }

    struct sockaddr_in clnt_addr;
    int clnt_addr_size = sizeof(clnt_addr);

    for (int i = 0; i < 5; ++i) {
        int Clnt_sock = accept(Serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size);  // accept
        if (Clnt_sock == -1){
            ErrorHandling("accept() error");
        }
        else{
            printf("Connected client %d \n", i+1);
        }

        while(1) {
            int over = 0, recv_len = 0, msg_len, recv_cnt;
            char msg[BUF_SIZE];
            while (recv_len == 0 || recv_len < msg_len + Len_SIZE) {
                recv_cnt = recv(Clnt_sock, (char*)&msg[recv_len], BUF_SIZE, 0);
                if (recv_cnt == -1) {
                    ErrorHandling("read() error!");
                }
                if (recv_cnt == 0) {
                    over = 1;
                    break;
                }
                recv_len += recv_cnt;
                if (recv_len >= Len_SIZE) {
                    memcpy(&msg_len, msg, Len_SIZE);
                }
            }
            msg[recv_len] = '\0';

            if (over == 1) {
                break;
            }

            printf("Message from client: %s", msg + Len_SIZE); // output message from client
            fputs("Input message: ", stdout);
            fgets(msg + Len_SIZE, BUF_SIZE - Len_SIZE, stdin); // input message
            int len = strlen(msg + Len_SIZE);
            memcpy(msg, &len, Len_SIZE);
            send(Clnt_sock, msg, Len_SIZE + len, 0); // send message to client
        }
        closesocket(Clnt_sock);
    }

    closesocket(Serv_sock);
    return 0;
}

1-2--客户端

cpp 复制代码
// gcc string_client_win.c -o string_client_win -lwsock32
// string_client_win 127.0.0.1 9190

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#define BUF_SIZE 1024
#define Len_SIZE 4

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

int main(int argc, char* argv[]){

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

    WSADATA wsaData; // init socket lib
    if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
        ErrorHandling("WSAStartup() error!");
    }
    int sock = socket(PF_INET, SOCK_STREAM, 0);   // create socket
    if (sock == -1)
        ErrorHandling("socket() error");

    struct sockaddr_in serv_addr; // allocate ip, port
    memset(&serv_addr, 0, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));

    if (connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1){ // connect
        ErrorHandling("connect() error");
    }
    else {
        puts("Connected");
    }

    for(int i = 0; i < 3; i++) {
        char msg[BUF_SIZE];
        memset(msg, 0, BUF_SIZE);
        
        fputs("Input message: ", stdout);
        fgets(msg + Len_SIZE, BUF_SIZE - Len_SIZE, stdin); // input message
        int len = strlen(msg + Len_SIZE);
        memcpy(msg, &len, Len_SIZE);
        send(sock, msg, Len_SIZE + len, 0); // send message to server

        int recv_len = 0, msg_len = 0, recv_cnt = 0;
        while (recv_len == 0 || recv_len < msg_len + Len_SIZE) {
            recv_cnt = recv(sock, (char*)&msg, BUF_SIZE, 0);
            recv_len += recv_cnt;
            if (recv_len >= Len_SIZE) {
                memcpy(&msg_len, msg, Len_SIZE);
            }
        }
        msg[recv_len] = '\0';
        printf("Message from server: %s", msg + Len_SIZE);
    }

    closesocket(sock);
    return 0;
}

1-3--编译运行

bash 复制代码
# 服务器端
gcc string_server_win.c -o string_server_win -lwsock32
string_server_win 9190

# 客户端
gcc string_client_win.c -o string_client_win -lwsock32
string_client_win 127.0.0.1 9190

1-4--基于 linux 实现

项目链接:Chapter5

2--基于TCP实现文件传输

相关推荐
Hacker_LaoYi13 小时前
【漏洞分析】DDOS攻防分析(四)——TCP篇
网络·tcp/ip·ddos
爱吃水果蝙蝠汤13 小时前
DATACOM-IP单播路由(BGP)-复习-实验
网络·网络协议·tcp/ip
loong_XL15 小时前
服务器ip:port服务用nginx 域名代理
服务器·tcp/ip·nginx
从后端到QT19 小时前
boost asio 异步服务器
服务器·网络·tcp/ip
手心里的白日梦20 小时前
网络计算器的实现:TCP、守护进程、Json、序列化与反序列化
网络·tcp/ip·json
言成言成啊20 小时前
TCP与UDP的端口连通性
网络协议·tcp/ip·udp
敲代码娶不了六花20 小时前
对计算机网络中“层”的理解
网络·网络协议·tcp/ip·计算机网络
昌sit!1 天前
监控IP频繁登录服务器脚本
服务器·网络·tcp/ip
凹凸撒man1 天前
AUTOSAR TCP中的MSS和MTU的关系
网络·tcp/ip·autosar
衣舞晨风2 天前
内网IP段介绍与汇总
网络·tcp/ip·ipv4·内网·网段