网络编程之客户端聊天(服务器加客户端共三种方式)

最终效果:

serve.c

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/select.h>

#define MAX_CLIENTS 2  // 只允许两个客户端
#define BUF_SIZE 1024

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("请输入端口号\n");
        return 1;
    }
    int port = atoi(argv[1]);

    int server_fd, client_fd, max_fd, activity, valread;
    int client_sockets[MAX_CLIENTS] = {0};  // 存储客户端 socket
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[BUF_SIZE];

    fd_set read_fds;  // 监听集合

    // 创建服务器 socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("Socket 创建失败");
        exit(1);
    }

    // 绑定地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("绑定失败");
        exit(1);
    }

    // 监听连接
    if (listen(server_fd, 5) < 0) {
        perror("监听失败");
        exit(1);
    }

    printf("服务器启动,等待客户端连接...\n");

    while (1) {
        FD_ZERO(&read_fds);
        FD_SET(server_fd, &read_fds);
        max_fd = server_fd;

        // 添加客户端 socket
        for (int i = 0; i < 2; i++) {
            int sock = client_sockets[i];
            if (sock > 0) FD_SET(sock, &read_fds);
            if (sock > max_fd) max_fd = sock;
        }

        // 监听 socket 活动
        activity = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
        if (activity < 0) {
            perror("select 错误");
            exit(1);
        }

        // 处理新连接
        if (FD_ISSET(server_fd, &read_fds)) {
            client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);
            if (client_fd < 0) {
                perror("接受客户端失败");
                continue;
            }
            printf("新客户端连接\n");

            // 存入数组
            for (int i = 0; i < MAX_CLIENTS; i++) {
                if (client_sockets[i] == 0) {
                    client_sockets[i] = client_fd;
                    break;
                }
            }
        }

        // 处理客户端消息
        for (int i = 0; i < 2; i++) {
            int sock = client_sockets[i];
            if (FD_ISSET(sock, &read_fds)) {
                valread = read(sock, buffer, BUF_SIZE);
                if (valread == 0) {
                    printf("客户端断开连接\n");
                    close(sock);
                    client_sockets[i] = 0;
                } else {
                    buffer[valread] = '\0';
                    printf("客户端发送: %s\n",buffer);

                    // 找到另一个客户端
                    int other_client = (i == 0) ? client_sockets[1] : client_sockets[0];
                    if (other_client != 0) {
                        send(other_client, buffer, strlen(buffer), 0);
                    }
                }
            }
        }
    }

    return 0;
}

client1.c

复制代码
#include <head.h>


#define BUF_SIZE 1024

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("请输入端口号\n");
        return 1;
    }
    char *server_ip ="192.168.61.94";
    int port = atoi(argv[1]);

    int sock;
    struct sockaddr_in server_addr;
    char buffer[BUF_SIZE];

    struct pollfd fds[2];

    // 创建 socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("Socket 创建失败");
        exit(1);
    }

    // 连接服务器
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("连接失败");
        exit(1);
    }

    printf("连接服务器成功,开始聊天...\n");

    fds[0].fd = sock;
    fds[0].events = POLLIN;
    fds[1].fd = STDIN_FILENO;
    fds[1].events = POLLIN;

    while (1) {
        poll(fds, 2, -1);

        if (fds[0].revents & POLLIN) {
            int len = read(sock, buffer, BUF_SIZE);
            if (len <= 0) {
                printf("服务器断开连接\n");
                break;
            }
            buffer[len] = '\0';
	printf("%s", buffer);
        }

        if (fds[1].revents & POLLIN) {
            fgets(buffer, BUF_SIZE, stdin);
            send(sock, buffer, strlen(buffer), 0);
        }
    }

    close(sock);
    return 0;
}

client2.c

复制代码
#include <head.h>

#define BUF_SIZE 1024

int sock;

void *receive_messages(void *arg) {
    char buffer[BUF_SIZE];
    while (1) {
        int len = read(sock, buffer, BUF_SIZE);
        if (len <= 0) {
            printf("服务器断开连接\n");
            exit(1);
        }
        buffer[len] = '\0';
        printf("%s", buffer);

    }
    return NULL;
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("请输入端口号\n");
        return 1;
    }
    char *server_ip ="192.168.61.94";
    int port = atoi(argv[1]);

    struct sockaddr_in server_addr;
    char buffer[BUF_SIZE];

    sock = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    printf("连接服务器成功,开始聊天...\n");
    pthread_t recv_thread;
    pthread_create(&recv_thread, NULL, receive_messages, NULL);

    while (1) {
        fgets(buffer, BUF_SIZE, stdin);
        send(sock, buffer, strlen(buffer), 0);
    }

    close(sock);
    return 0;
}
相关推荐
爱装代码的小瓶子30 分钟前
Linux下的权限与文件
linux·运维·服务器
励志不掉头发的内向程序员1 小时前
【Linux系列】解码 Linux 内存地图:从虚拟到物理的寻宝之旅
linux·运维·服务器·开发语言·学习
Fuly10242 小时前
使用docker本地部署dify
运维·docker·容器
拥友LikT2 小时前
计算机网络基础篇——计算机网络概述
网络·计算机网络
海洲探索-Hydrovo4 小时前
TTP Aether X 天通透传模块丨国产自主可控大数据双向通讯定位模组
网络·人工智能·科技·算法·信息与通信
ybb_ymm7 小时前
mysql8在linux下的默认规则修改
linux·运维·数据库·mysql
半梦半醒*7 小时前
zabbix安装
linux·运维·前端·网络·zabbix
南尘NCA86668 小时前
企业微信防封防投诉拦截系统:从痛点解决到技术实现
java·网络·企业微信
Panda__Panda8 小时前
docker项目打包演示项目(数字排序服务)
运维·javascript·python·docker·容器·c#
xx.ii8 小时前
Docker监控
运维·docker·容器