TCP多进程并发服务器与单进程客户端(简单回声)echo clinet

文章详细介绍了如何在C语言中实现TCP协议的多进程并发服务器,包括创建套接字、绑定、监听、处理客户端连接,以及单进程TCP客户端的连接过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

TCP 多进程并发服务器: 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <arpa/inet.h>

int sig_f = 0;
void FuncSigInt(int sig);
int   start_echo_server(int argc, char *argv[]);
void  init_signal_handle(void);

int main(int argc, char *argv[]) {
    
    if (argc < 3) {
        printf("Please use: %s <IP listen_address> <server_listen_port> <server_vcd>\n", argv[0]);
        return 1;
    }
    
    return start_echo_server(argc, argv);
}
void FuncSigInt(int sig) {
    printf("[srv] SIGINT is coming!\n");
    sig_f = 1;
}

void  init_signal_handle(void){
    struct sigaction sa;
    sa.sa_flags = 0;
    sa.sa_handler = FuncSigInt;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGINT,&sa,NULL);
}

int start_echo_server(int argc, char *argv[]){
   
    const char *server_listen_fd = argv[1];
    int server_listen_port = atoi(argv[2]);
    const char *server_vcd = argv[3];
    
    init_signal_handle();
    
    int server_fd, client_socket;
    struct sockaddr_in listen_address;
    int addrlen = sizeof(listen_address);

    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    listen_address.sin_family = AF_INET;
    listen_address.sin_addr.s_addr = inet_addr(server_listen_fd);
    listen_address.sin_port = htons(server_listen_port);

    // 绑定套接字到指定端口
    if (bind(server_fd, (struct sockaddr *)&listen_address, sizeof(listen_address)) < 0) {
        perror("bind failed");
        return -1;
    }

    // 监听端口,等待连接
    if (listen(server_fd, 3) < 0) {
        perror("listen failed");
        return -1;
    }

    printf("[srv] server[%s:%d][%s] is initializing!\n",server_listen_fd,server_listen_port,server_vcd);
    while (!sig_f) {
        if ((client_socket = accept(server_fd, (struct sockaddr *)&listen_address, (socklen_t *)&addrlen)) < 0) {
            if(errno == EINTR){
                continue;
            }else{
                return -1;
              }
        }
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &(listen_address.sin_addr), client_ip, INET_ADDRSTRLEN);
        printf("[srv] client[%s:%d] is accepted!\n",client_ip,ntohs(listen_address.sin_port));

        char buffer[128];
        ssize_t num_bytes;

        while (1) {
            memset(buffer, 0, sizeof(buffer));
            if ((num_bytes = read(client_socket, buffer, sizeof(buffer) - 1))<= 0) {
                break;
            }
            buffer[num_bytes] = '\0';
            printf("[ECH_RQT]%s", buffer);

            char reply_buffer[136];
            snprintf(reply_buffer, sizeof(reply_buffer), "(%s)%s", server_vcd, buffer);
            
            write(client_socket, reply_buffer, strlen(reply_buffer));
        }
        
        printf("[srv] client[%s:%d] is closed!\n",client_ip,ntohs(listen_address.sin_port));
        close(client_socket);
    }

    if (server_fd != -1) {
        close(server_fd);
    }
    return 0;
}

TCP单进程客户端:

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

int start_client(int argc, char *argv[]);

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

    if (argc != 3) {
        printf("请按正确参数使用: %s <ip_address> <port>\n", argv[0]);
        return 1;
    }

    return start_client(argc, argv);
}

int start_client(int argc, char *argv[]){
    char* ip_address = argv[1];
    int port = atoi(argv[2]);

    struct sockaddr_in server_address;
    int sockfd;

    // Create a socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return 1;
    }

    // Set server address
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(port);
    if (inet_pton(AF_INET, ip_address, &(server_address.sin_addr)) <= 0) {
        perror("inet_pton");
        return 1;
    }

    // Connect to the server
    if (connect(sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) == -1) {
        perror("connect");
        return 1;
    }

    printf("[cli] server[%s:%d] is connected!\n", ip_address, port);

    char input_buffer[138];
    ssize_t num_bytes;

    while (1) {
        memset(input_buffer, 0, sizeof(input_buffer));
        if (fgets(input_buffer, sizeof(input_buffer), stdin) == NULL) {
            break;
        }

        printf("[ECH_RQT]%s", input_buffer);
        
        if (strncmp(input_buffer, "EXIT\n",5) == 0) {
            break;
        }
        write(sockfd, input_buffer, strlen(input_buffer));

        char buffer[138];
        ssize_t num_bytes;
        memset(buffer, 0, sizeof(buffer));
        num_bytes = read(sockfd, buffer, sizeof(buffer) - 1);

        if (num_bytes <= 0) {
            break;
        }

        buffer[num_bytes] = '\0';
        printf("[ECH_REP]%s", buffer);
        
    }
    close(sockfd);
    printf("[cli] connfd is closed!");
    printf("[cli] clinet is to return!");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值