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

相关推荐
C++忠实粉丝1 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
九州ip动态1 小时前
做网络推广及游戏注册为什么要换IP
网络·tcp/ip·游戏
Estar.Lee2 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
速盾cdn9 小时前
速盾:CDN是否支持屏蔽IP?
网络·网络协议·tcp/ip
yaoxin5211239 小时前
第二十七章 TCP 客户端 服务器通信 - 连接管理
服务器·网络·tcp/ip
内核程序员kevin9 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
JosieBook17 小时前
【网络工程】查看自己电脑网络IP,检查网络是否连通
服务器·网络·tcp/ip
inter_peng18 小时前
[Docker-显示所有容器IP] 显示docker-compose.yml中所有容器IP的方法
tcp/ip·docker·eureka
九州ip动态21 小时前
模拟器多开限制ip,如何设置单窗口单ip,每个窗口ip不同
tcp/ip·游戏·媒体