《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实现文件传输

相关推荐
hgdlip1 小时前
有什么办法换网络ip动态
网络·tcp/ip·智能路由器
城南vision11 小时前
计算机网络——TCP篇
网络·tcp/ip·计算机网络
Tony聊跨境12 小时前
独立站SEO类型及优化:来检查这些方面你有没有落下
网络·人工智能·tcp/ip·ip
方方怪16 小时前
与IP网络规划相关的知识点
服务器·网络·tcp/ip
xiaoxiongip66621 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
懒大王就是我1 天前
C语言网络编程 -- TCP/iP协议
c语言·网络·tcp/ip
海绵波波1071 天前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
幺零九零零1 天前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
ZachOn1y1 天前
计算机网络:运输层 —— 运输层概述
网络·tcp/ip·计算机网络·运输层
乌龟跌倒2 天前
网络层3——IP数据报转发的过程
网络·tcp/ip·计算机网络·智能路由器