【Linux C | 网络编程】简易的多人在线聊天室

一、多线程实现

每当有一个客户端连接上,就创建一个专门线程与这个客户端通信,在线程里面不停的接受这个客户端发来的消息,如果有一个100客户端就会产生100个线程去接受每一个客户端的消息,从而实现了多人在线的效果服务器

二、创建一个简易的服务器

上篇文章有教程【Linux C | 网络编程】| IPv4地址族、IPv4地址族和字符地址间的转换、简易的TCP连接-CSDN博客

三、服务器多线程

服务器每被客户机连接一次,就会创建一个对应子线程。

子线程负责实现对客户机的读写功能。

同时子线程要判断对应客户机的状态,如果该客户机退出, read 函数返回 0 ,将状态值val 设为1,修改转发信息,再退出线程。

//创建一个简易的多人聊天室
#include <myhead.h>

//定义结构体来接收客户端的网络地址
struct sockaddr_in CliAddr;
int len = sizeof(CliAddr);

//定义一个数组来接收客户端socket号,用来创建多线程
int clientIdArr[999];
int clientIndex = 0; //用来记录数组的下标

int val; //定义一个状态值
//线程作用函数
void *func(void *p)
{
    int fd = *(int *)p;
    while (1)
    {
        char buf[512];
        if (read(fd, buf, sizeof(buf)) <= 0) //判断文件(客户端)是否存在
        {
            val = 1;
        }
        //转发信息
        for (int i = 0; i < clientIndex; i++)
        {
            if (fd != clientIdArr[i])
            {
                if (val == 1)
                {
                    //转发内容,如果没有客户机退出则不执行
                    char arr[128];
                    inet_ntop(AF_INET, &CliAddr.sin_addr.s_addr, arr, sizeof(arr));
                    sprintf(buf, "网络地址为%s:%d的客户机退出了群聊", arr, ntohs(CliAddr.sin_port));
                }
                write(clientIdArr[i], buf, sizeof(buf));
            }
        }
        //客户机退出,服务器则结束该线程
        if (val == 1)
        {
            break;
        }
    }

    return NULL;
}
int main(int argc, const char *argv[])
{

    //获取一个网络地址
    u_int32_t ip;
    inet_pton(AF_INET, "192.168.40.148", &ip);
    struct sockaddr_in addr;
    addr.sin_addr.s_addr = ip;
    addr.sin_port = htons(8881);
    addr.sin_family = AF_INET;

    // 1、获取一个socket
    int ListenSd = socket(AF_INET, SOCK_STREAM, 0);
    if (ListenSd < 0)
    {
        perror("");
        return -1;
    }

    // 2、绑定网络地址
    bind(ListenSd, (struct sockaddr *)&addr, sizeof(addr));

    // 3、监听连接
    listen(ListenSd, 5);

    while (1)
    { 
        // 4、等待连接
        int clientID = accept(ListenSd, (struct sockaddr *)&CliAddr, &len);
        if (clientID < 0)
        {
            perror("accept error");
            return -1;
        }
        //将接收到的套接字存入数组
        clientIdArr[clientIndex] = clientID;
        //把数字网络地址转为字符串地址
        char arr[128];
        inet_ntop(AF_INET, &CliAddr.sin_addr.s_addr, arr, sizeof(arr));
        printf("ip地址为%s的%d端口连接上了该服务器\n", arr, ntohs(CliAddr.sin_port));
        //创建子线程,传入参数是连接到的套接字ID
        pthread_t ptid;
        pthread_create(&ptid, NULL, func, &clientIdArr[clientIndex]);
        clientIndex++;
    }

    //绑定

    return 0;
}

四、客户机多线程

客户机的主线程对服务器发送信息,子线程接收服务器信息,同时判断服务器的信息,如果服务器异常退出,则断开连接退出程序。

#include <myhead.h>
//线程工作函数
void *func(void *p)
{
    int fd = *(int *)p;
    while (1)
    {
        char buf[512];
        //判断服务器的状态
        if(read(fd, buf, sizeof(buf)) <= 0)
        {
            printf("服务器异常,程序退出\n");
            exit(0);
        }
        printf("收到了%s\n", buf);
    }
}
int main(int argc, const char *argv[])
{
    //获取一个网络地址
    u_int32_t ip;
    inet_pton(AF_INET, "192.168.40.148", &ip);
    struct sockaddr_in addr;
    addr.sin_addr.s_addr = ip;
    addr.sin_port = htons(8881);
    addr.sin_family = AF_INET;

    // 1、获取一个socket
    int sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0)
    {
        perror("");
        return -1;
    }
    //连接主机

    if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("connect error");
        return -1;
    }
    //定义一个线程来接收信息
    pthread_t ptid;
    pthread_create(&ptid, NULL, func, &sd);
    
    //发送信息
    while (1)
    {
        char buf[512];
        scanf("%s", buf);
        write(sd, buf, sizeof(buf));
    }

    return 0;
}

五、一些转换函数的补充

在编写该代码的时候,老是混淆 ip的 数字和字符串的转换函数。

还有端口号网络字节序和主机字节序的转换

inet_pton :

用于把字符串IP转换为数字ip;

 u_int32_t ip;
    inet_pton(AF_INET, "192.168.40.148", &ip);

inet_ntop:

把数字ip转换为字符串IP;

char arr[128];
inet_ntop(AF_INET, &CliAddr.sin_addr.s_addr, arr, sizeof(arr));

htons :16位

htonl:32位

将主机字节序转换为网络字节序

ntohs:16位

ntohl:32位

将网络字节序转位主机字节序

六、总结

只要理清思路和熟悉函数,实现该程序还是不难

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux下使用C语言实现多人会话聊天室需要基于网络编程的一些知识和技术。下面是具体的功能实现: 1. 注册与登录系统:聊天室的用户需要进行注册和登录才能使用。通过使用TCP协议,可以使用Socket编程在服务器端实现注册和登录功能。用户可以通过客户端向服务器发送注册信息,服务器将注册信息保存到数据库中。对于登录功能,用户输入用户名和密码后,服务器端验证登录信息,如果验证通过则将用户标记为已登录。 2. 建立连接与断开连接:在多人会话聊天室中,用户需要可以与服务器建立连接并断开连接。这可以通过使用TCP协议和Socket编程来实现。用户在客户端输入服务器的IP地址和端口号后,客户端与服务器建立连接。断开连接时,用户可以发送指定命令给服务器端关闭与服务器的连接。 3. 聊天功能:在多人会话聊天室中,用户可以发送消息给其他用户。这可以通过使用TCP协议和Socket编程来实现。客户端向服务器发送聊天消息,服务器收到消息后将消息广播给所有在线用户。其他用户通过服务器转发的消息进行聊天。 4. 用户管理:多人会话聊天室需要管理用户信息,包括用户的注册信息、在线状态等。服务器将用户的注册信息保存到数据库中,并记录用户的登录状态。服务器端可以实时检测用户的连接状态,并及时更新用户的在线状态。 以上是在Linux下使用C语言实现多人会话聊天室的基本功能。通过网络编程C语言的结合,可以实现一个简单而功能完善的多人会话聊天室

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值