分享

嵌入式中,TCP server如何与多个client通信?(附代码)

 新用户0118F7lQ 2022-06-27 发布于浙江

大家好,我是LinuxZn。

上一篇文章我们分享了嵌入式中,TCP通信常用接口的使用封装,其demo中我们只是简单地实现一对一的收发。

但是实际开发中,tcp server是要支持与多个client同时进行通信的,本篇分享一对多的收发,也即tcp server并发处理。

tcp server实现并发的方式有:多进程、多线程。

多进程开销比较大,不常用。本篇笔记我们分享多线程的方法。

简单的demo

tcp_server.c:

左右滑动查看全部代码>>>

#include <pthread.h>
#include 'tcp_socket.h'

static pthread_t cli_data_proce_thread_tid;

static void *process_client_data(void *arg)
{
    int client_fd = *(int*)arg;

    while (1)
    {
        char buf[128] = {0};
        
        int recv_len = tcp_blocking_recv(client_fd, buf, sizeof(buf));
        if (recv_len <= 0)
        {
            printf('recv error!\n');
            tcp_close(client_fd);
            return NULL;
        }
        printf('client_fd = %d, recv : %s\n', client_fd, buf);

        int send_len = tcp_send(client_fd, buf, strlen(buf));
        if (send_len <= 0)
        {
            printf('send error!\n');
            tcp_close(client_fd);
            return NULL;
        }
        else
        {
            printf('send success! send: %s, send_len: %d\n', buf, send_len);
        }
        usleep(10 * 1000);
    }
}

int main(int argc, char **argv)
{
    printf('==================tcp server==================\n');
    int server_fd = tcp_init(NULL4321);

    while (1)
    {
        int new_fd = tcp_accept(server_fd);

        // 创建客户端数据处理线程
        int ret = pthread_create(&cli_data_proce_thread_tid, NULL, process_client_data, (void*)&new_fd);
        if(ret != 0)
        {
            perror('pthread_create');
            exit(EXIT_FAILURE);
        }
    }

    tcp_close(server_fd);

    return 0;
}

主线程,监听客户端连接;cli_data_proce_thread_tid线程处理客户端数据。下面我们创建4个client与该server进行连接。

首先,需要注意的是,我们创建tcp_server的方式为:

左右滑动查看全部代码>>>

int server_fd = tcp_init(NULL4321);
int tcp_init(const char* ip, int port)
{
    int optval = 1
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror('socket');
        return -1;
    }

    /* 解除端口占用 */
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
 {
  perror('setsockopt\n');
  return -1;
 }

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (NULL == ip)
    {
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    }
    else
    {
        server_addr.sin_addr.s_addr = inet_addr(ip); 
    }

    if (bind(server_fd, (struct sockaddr*)&server_addr,sizeof(struct sockaddr)) < 0)
    {
        perror('bind');
        close(server_fd);
        return -1;
    }

    if(listen(server_fd, MAX_CONNECT_NUM) < 0)
    {
        perror('listen');
        close(server_fd);
        return -1;
    }

    return server_fd;
}

我们使用INADDR_ANY来创建server。

INADDR_ANY:表示不确定地址,或所有地址、任意地址。也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。

图片

我们本机所有网卡的IP:

192.168.1.107
127.0.0.1

我们的本机上的client(client的代码见上一节)连接这两个IP都可以连上server。

下面使用我们本机上两个client连接server并进行数据交互:

图片

Windows的网络助手链接server:

图片

我们再开一个Ubuntu虚拟机,上面的client连接该server:

图片
图片

以上就是本次demo演示的server同时与4个client通信的小实验。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多