C语言 网络编程(十三)并发的TCP服务端-以进程完成功能

简介: 这段代码实现了一个基于TCP协议的多进程并发服务端和客户端程序。服务端通过创建子进程来处理多个客户端连接,解决了粘包问题,并支持不定长数据传输。客户端则循环发送数据并接收服务端回传的信息,同样处理了粘包问题。程序通过自定义的数据长度前缀确保了数据的完整性和准确性。

网络(十三)并发的TCP服务端-以进程完成功能

服务端程序

// todo TCP多进程服务端程序 循环接收客户端数据,将数据回传,解决粘包问题,不定长的数据传输
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#define N 128

//初始化socket
int  init_socket(char *ip,char *port){
   
    int init_socket_fd= socket(AF_INET,SOCK_STREAM,0);
    if (init_socket_fd==-1){
   
        printf("init_socket err");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server_addr;
    socklen_t len=sizeof(server_addr);
    bzero(&server_addr,len);
    server_addr.sin_family=AF_INET;
    inet_aton(ip,&server_addr.sin_addr);
    server_addr.sin_port= htons(atoi(port));

    int bind_ret= bind(init_socket_fd,(struct sockaddr*)&server_addr,len);
    if (bind_ret == -1) {
   
        printf("bind error\n");
        exit(EXIT_FAILURE);
    }

    int listen_ret= listen(init_socket_fd,10);
    if (listen_ret == -1) {
   
        printf("listen error\n");
        exit(EXIT_FAILURE);
    }


    return init_socket_fd;
}

//客户端发送消息
int  Server_Send_data(int clientFD,char* msg){
   
    strcat(msg,"-回传");


    int server_send_len=send(clientFD,msg,strlen(msg),0);
    if (server_send_len == -1) {
   
        printf("send error\n");
        exit(EXIT_FAILURE);
    }if (server_send_len == 0) {
   
        printf("客户端关闭连接\n");
        return -1;
    }
    printf("发送给客户端数据:[%s]\n",msg);
    return 0;
}


//接收数据
int Server_Receive_data(int clientFD){
   
    while (1){
   
        //接收-使用新的文件描述符
        //先接收四字节的长度
        int msg_len=0;
        int total_received=0;

        int recv_len=recv(clientFD,&msg_len,4,0);
        if (recv_len == -1) {
   
            printf("recv error\n");
            exit(EXIT_FAILURE);
        }
        if (recv_len == 0) {
   
            printf("客户端关闭连接\n");
            break;
        }

        while (1){
   
            char recv_buf[N];
            bzero(recv_buf,N);
            recv_len = recv(clientFD, recv_buf+total_received, msg_len-total_received, 0);
            if (recv_len == -1) {
   
                printf("recv error\n");
                exit(EXIT_FAILURE);
            }
            if (recv_len == 0) {
   
                break;
            }
            if (strncmp(recv_buf, "exit", 4) == 0) {
   
                printf("客户端退出通信\n");
                close(clientFD);
                return 0;
            }
            total_received+=recv_len;
            printf("收到客户端消息:|%s|\n",recv_buf);

            //Server_Send_data(clientFD, recv_buf);
        }

    }
    return 0;
}

void do_client(int cfd){
   
    Server_Receive_data(cfd);
    close(cfd);
    exit(EXIT_SUCCESS);
}

void do_sigchld_handler(int sig)
{
   
    wait(NULL);
}

int main(){
   
    __sighandler_t retsig;
    retsig = signal(SIGCHLD,do_sigchld_handler);
    if (retsig == SIG_ERR){
   
        perror("[ERROR] signal(): ");
        exit(EXIT_FAILURE);
    }
    int socket_fd = init_socket("172.17.140.183","8081");

    struct sockaddr_in cli_addr;
    socklen_t cli_len=sizeof(cli_addr);

    while (1){
   
        bzero(&cli_addr,cli_len);
        //获取客户端连接
        int clientFD= accept(socket_fd,(struct sockaddr*)&cli_addr,&cli_len);
        if (clientFD == -1){
   
            printf("accept error\n");
            exit(EXIT_FAILURE);
        }

        printf("连接 ip:%s, port:%d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));

        int pid=fork();
        if (pid == -1){
   
            printf("fork error\n");
            close(clientFD);
            exit(EXIT_FAILURE);
        }else if (pid == 0) {
   
            //子进程处理客户端请求
            do_client(clientFD);
        }

    }

}

客户端程序


//todo tcp多进程客户端,循环发送数据,接收回传数据,解决粘包问题,不定长的数据传输
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define N 128
//初始化socket
int  init_socket(char *ip,char *port){
   

    int init_socket_fd= socket(AF_INET,SOCK_STREAM,0);
    if (init_socket_fd==-1){
   
        printf("init_socket err");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server_addr;
    socklen_t len=sizeof(server_addr);
    bzero(&server_addr,len);
    server_addr.sin_family=AF_INET;
    inet_aton(ip,&server_addr.sin_addr);
    server_addr.sin_port= htons(atoi(port));

    //连接
    int ret= connect(init_socket_fd,(struct sockaddr*)&server_addr,len);
    if (ret==-1){
   
        printf("connect error,连接失败\n");
        exit(EXIT_FAILURE);
    }


    return init_socket_fd;
}

//客户端接收数据
int Client_Receive_data(int socket_fd){
   
    char receive_msg[N];
    bzero(receive_msg,N);
    int recv_len= recv(socket_fd, receive_msg,sizeof(receive_msg),0);
    if (recv_len == -1) {
   
        printf("recv error\n");
        exit(EXIT_FAILURE);
    }

    receive_msg[recv_len] = '\0';
    printf("收到客户端数据:[%s]\n",receive_msg);
}


//客户端发送数据
int  Client_Send_data(int socket_fd){
   
    char msg[N];

    while (1){
   
        bzero(&msg, sizeof (msg));
        printf("请输入:\n");
        fgets(msg, sizeof(msg),stdin);
        msg[strlen(msg)-1]='\0';

        printf("发送数据%s\n",msg);

        //粘包解决
        int old_msg_length= strlen(msg);
        char *New_msg=(char *) malloc(old_msg_length+4);
        memcpy(New_msg,&old_msg_length,4);
        memcpy(New_msg+4,msg,old_msg_length);


        int  Send_data_len= send(socket_fd,New_msg, old_msg_length+4,0);
        if (Send_data_len==-1){
   
            printf("发送失败 send err\n");
            exit(EXIT_FAILURE);
        }
        printf("发送了%d个字节\n",Send_data_len);

        free(New_msg);

        if (strncmp(msg, "exit", 4) == 0) {
   
            printf("退出通信\n");
            close(socket_fd);
            break;
        }
        //接收
        //Client_Receive_data(socket_fd);

    }

    return 0;
}

int main(){
   
    //初始化连接
    int socket_fd = init_socket("172.17.140.183","8081");
    //发送数据
    Client_Send_data(socket_fd);


    return 0;
}
相关文章
|
3月前
|
网络协议 Unix C语言
C语言 网络编程(十六)广播和组播
广播和组播是网络通信的重要方式。广播允许一台主机向子网内所有主机发送数据包,常用于局域网内的消息传播;组播则将数据包发送给特定的一组主机,适用于视频会议等应用场景。广播地址如 `192.168.1.255` 用于同一子网的所有主机。组播地址如 `224.0.0.0` 至 `239.255.255.255` 标识特定主机群。C语言示例展示了如何通过 UDP 实现广播和组播通信。此外,UNIX域套接字用于同一机器上进程间的高效通信。
187 14
|
3月前
|
网络协议 算法 网络性能优化
C语言 网络编程(十五)套接字选项设置
`setsockopt()`函数用于设置套接字选项,如重复使用地址(`SO_REUSEADDR`)、端口(`SO_REUSEPORT`)及超时时间(`SO_RCVTIMEO`)。其参数包括套接字描述符、协议级别、选项名称、选项值及其长度。成功返回0,失败返回-1并设置`errno`。示例展示了如何创建TCP服务器并设置相关选项。配套的`getsockopt()`函数用于获取这些选项的值。
|
3月前
|
网络协议 C语言
C语言 网络编程(十四)并发的TCP服务端-以线程完成功能
这段代码实现了一个基于TCP协议的多线程服务器和客户端程序,服务器端通过为每个客户端创建独立的线程来处理并发请求,解决了粘包问题并支持不定长数据传输。服务器监听在IP地址`172.17.140.183`的`8080`端口上,接收客户端发来的数据,并将接收到的消息添加“-回传”后返回给客户端。客户端则可以循环输入并发送数据,同时接收服务器回传的信息。当输入“exit”时,客户端会结束与服务器的通信并关闭连接。
|
3月前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
72 0
|
4天前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
41 17
|
14天前
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
|
15天前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
39 10
|
17天前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,并提供一些实用的代码示例。通过阅读本文,您将了解到如何保护自己的网络安全,以及如何提高自己的信息安全意识。
44 10
|
17天前
|
存储 监控 安全
云计算与网络安全:云服务、网络安全、信息安全等技术领域的融合与挑战
本文将探讨云计算与网络安全之间的关系,以及它们在云服务、网络安全和信息安全等技术领域中的融合与挑战。我们将分析云计算的优势和风险,以及如何通过网络安全措施来保护数据和应用程序。我们还将讨论如何确保云服务的可用性和可靠性,以及如何处理网络攻击和数据泄露等问题。最后,我们将提供一些关于如何在云计算环境中实现网络安全的建议和最佳实践。
|
18天前
|
监控 安全 网络安全
网络安全与信息安全:漏洞、加密与意识的交织
在数字时代的浪潮中,网络安全与信息安全成为维护数据完整性、保密性和可用性的关键。本文深入探讨了网络安全中的漏洞概念、加密技术的应用以及提升安全意识的重要性。通过实际案例分析,揭示了网络攻击的常见模式和防御策略,强调了教育和技术并重的安全理念。旨在为读者提供一套全面的网络安全知识框架,从而在日益复杂的网络环境中保护个人和组织的资产安全。
下一篇
DataWorks