项目:完成局域网CS模型,局域网内一个服务器,多个客户端连接一个服务器,完成局域网聊天。

news/2024/9/18 12:56:20/ 标签: 服务器, 网络

server.c

#include<myhead.h>


#define SERPORT 8888
#define SERIP "192.168.0.169"
#define BACKLOG 20

typedef struct {
    int newfd; // 存储新文件描述符
    struct sockaddr_in cin; // 存储客户端信息
} HMY;

void *fun1(void *sss) {
    HMY *msg = (HMY *)sss;
    int newfd = msg->newfd;
    struct sockaddr_in cin = msg->cin; // 解析客户端信息
    char buff[1024];

    while (1) {
        bzero(buff, sizeof(buff));
        int len = recv(newfd, buff, sizeof(buff), 0);
        if (len <= 0) {
            printf("客户端 %s:%d 退出\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
            break;
        }
        printf("收到来自 %s:%d 的信息:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buff);
        
        // 发送消息给所有连接的客户端
        send(newfd, buff, len, 0); // 回送消息
        printf("发送成功\n");
    }

    close(newfd); // 关闭客户端连接
    free(msg); // 释放内存
    pthread_exit(NULL);
}

int main(int argc, const char *argv[]) {
    int oldfd = socket(AF_INET, SOCK_STREAM, 0); // 1、创建套接字
    if (oldfd == -1) {
        perror("socket");
        return -1;
    }

    int atao = 1;
    if (setsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, &atao, sizeof(atao)) == -1) {
        perror("setsockopt");
        return -1;
    }
    printf("端口号快速复用成功\n");

    struct sockaddr_in sin = {
        .sin_family = AF_INET,
        .sin_port = htons(SERPORT),
        .sin_addr.s_addr = inet_addr(SERIP)
    };

    if (bind(oldfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { // 2、绑定
        perror("bind");
        return -1;
    }

    if (listen(oldfd, BACKLOG) == -1) { // 3、监听成功
        perror("listen");
        return -1;
    }
    printf("监听成功\n");

    while (1) {
        struct sockaddr_in cin;
        socklen_t cinlen = sizeof(cin);
        int newfd = accept(oldfd, (struct sockaddr *)&cin, &cinlen); // 接收客户端请求
        if (newfd == -1) {
            perror("accept");
            continue; // 继续接受其他连接
        }
        printf("%s:%d 发来请求\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));

        HMY *msg = malloc(sizeof(HMY)); // 动态分配内存
        if (msg == NULL) {
            perror("malloc");
            close(newfd);
            continue; // 处理内存分配失败
        }
        msg->newfd = newfd;
        msg->cin = cin;

        pthread_t tid;
        if (pthread_create(&tid, NULL, fun1, msg) != 0) {
            perror("pthread_create");
            free(msg); // 释放内存
            close(newfd);
            continue; // 处理线程创建失败
        }
        pthread_detach(tid); // 线程分离
    }

    close(oldfd); // 关闭旧的描述符
    return 0;
}
 

client.c 

#include<myhead.h>


#define SERVER_IP "192.168.0.169"
#define SERVER_PORT 8888

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return -1;
    }

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connect");
        close(sockfd);
        return -1;
    }

    printf("连接到服务器 %s:%d\n", SERVER_IP, SERVER_PORT);

    char buff[1024];
    while (1) {
        printf("请输入消息 (输入 'exit' 退出): ");
        fgets(buff, sizeof(buff), stdin);
        buff[strcspn(buff, "\n")] = 0; // 去掉换行符

        if (strcmp(buff, "exit") == 0) {
            break; // 退出循环
        }

        send(sockfd, buff, strlen(buff), 0); // 发送消息

        // 接收服务器的回送消息
        bzero(buff, sizeof(buff));
        int len = recv(sockfd, buff, sizeof(buff), 0);
        if (len > 0) {
            printf("服务器回送: %s\n", buff);
        }
    }

    close(sockfd); // 关闭连接
    return 0;
}
 


http://www.ppmy.cn/news/1525951.html

相关文章

[译] 当Go程序结束时会发生什么

本篇内容是根据2021年2月份When Go programs end音频录制内容的整理与翻译,两位主持人邀请Go团队的Michael Knyszek,讨论了当Go程序结束时会发生什么 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. Mat Ryer: 大家好&#xff0c;欢迎收听 Go Time。我是 Mat Ryer。今…

Mybatis-plus进阶篇(二)

文章目录 一.条件构造器方法1.eq使用范围方法签名参数说明示例 2.ne使用范围方法签名参数说明示例 3.gt使用范围方法签名参数说明示例 4.ge使用范围方法签名参数说明示例 5.lt使用范围方法签名参数说明示例 6.le使用范围方法签名参数说明示例 7.between使用范围方法签名参数说明…

18068 选择排序

### 思路 1. **初始化**&#xff1a;定义变量i, j, k和临时变量tmp。 2. **外层循环**&#xff1a;遍历数组的每个元素&#xff0c;i从0到n-2。 3. **内层循环**&#xff1a;从i1到n-1&#xff0c;找到最小元素的索引k。 4. **交换**&#xff1a;将最小元素与当前元素交换。 #…

矩阵直播换IP:如何使用代理IP提升直播效果

在直播行业中&#xff0c;稳定的网络连接和高质量的直播效果至关重要。然而&#xff0c;随着观众数量的增加和网络环境的复杂化&#xff0c;直播过程中可能会遇到网络波动、IP封禁等问题。通过使用代理IP&#xff0c;可以有效解决这些问题&#xff0c;提升直播效果。本文将详细…

Python | Leetcode Python题解之第406题根据身高重建队列

题目&#xff1a; 题解&#xff1a; class Solution:def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:people.sort(keylambda x: (-x[0], x[1]))n len(people)ans list()for person in people:ans[person[1]:person[1]] [person]return ans

SAP自动化-ME12批量更新最后一行的价格

Python源码 #-Begin-----------------------------------------------------------------#-Includes-------------------------------------------------------------- import sys, win32com.client import os import time#-Sub Main-----------------------------------------…

MacOS wine中文乱码问题

安装wine 1、brew update 执行失败&#xff0c;提示安装如下 2、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow 3、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow 3、brew update 4、brew in…

c语言是干嘛的

C语言是一种通用的、过程式的编程语言&#xff0c;主要用于系统编程、底层开发和各种高性能应用。它由丹尼斯里奇&#xff08;Dennis Ritchie&#xff09;于1972年在贝尔实验室开发&#xff0c;最初是为了实现UNIX操作系统。 C语言的主要用途&#xff1a; 系统编程&#xff1a…

RK3576芯片在智能家居里中型智慧屏产品的应用方案分析

智能家居在近年来得到了快速发展&#xff0c;AI技术不断发展&#xff0c;人机交互十分成熟&#xff0c;各种家电也都迎来了智能化浪潮&#xff0c;智能家居为人们提供了优秀的产品体验&#xff0c;受到主流消费者的青睐&#xff0c;智能家居里的中型智慧屏产品也随之兴起。 瑞芯…

多速率信号处理-插值和插值滤波器

插值意味着提高采样率&#xff0c;故而被称为上采样&#xff08;Up Sample&#xff09;。设原始序列为 x ( n ) x(n) x(n)&#xff0c;采样率为 f x f_x fx​&#xff0c;插值因子为 L L L&#xff0c;则插值的过程为原始序列每相邻两个样点之间插入 L − 1 L-1 L−1个 0 0 0构…

AI 加持的云端 IDE——三种方法高效开发前后端聊天交互功能

以下是「豆包 MarsCode 体验官」优秀文章&#xff0c;作者努力的小雨。 豆包 MarsCode 豆包MarsCode 编程助手支持的 IDE: 支持 Visual Studio Code 1.67.0 及以上版本&#xff0c;以及 JetBrains 系列 IDE&#xff0c;如 IntelliJ IDEA、Pycharm 等&#xff0c;版本要求为 22…

Nginx+Tomcat(负载均衡、动静分离)

目录 一、Nginx概述 1.Nginx应用 二、正向代理和反向代理 1.正向代理 1.1主要作用 1.2工作原理 2.反向代理 2.1主要作用 2.2工作原理 三、负载均衡模式 1.轮询 2.最少连接数 3.IP 哈希 4.加权轮询 5.最少时间算法 6.一致性哈希 四、规划部署负载均衡和反向…

HarmonyOS学习(十二)——数据管理(一)分布式数据

文章目录 1、分布式数据服务概述2、KV数据模型&#xff08;键值对数据库&#xff09;3、分布式数据服务的约束和限制4、接口说明5、分布式数据服务开发步骤5.1、导入模块5.2、构造分布式数据库管理类实例5.3、获取、创建分布式数据库5.4、订阅分布式数据库的数据变化5.5、插入数…

canal.adapter同步 ES 索引创建 大概配置详情

canal.adapter同步 ES 索引创建 大概配置详情 PUT /test {"settings": {"number_of_shards": 1,"number_of_replicas": 0,"analysis": {"analyzer": {"htmlStripAnalyzer": {"filter": ["lower…

LabVIEW多语言支持优化

遇到的LabVIEW多语言支持问题&#xff0c;特别是德文显示乱码以及系统区域设置导致的异常&#xff0c;可能是由编码问题或区域设置不匹配引起的。以下是一些可能的原因及解决方案&#xff1a; 问题原因&#xff1a; 编码问题&#xff1a;LabVIEW内部使用UTF-8编码&#xff0c;但…

【鸿蒙开发 day12】

鸿蒙开发-布局进阶 一.定位1.绝对定位2.相对定位3.定位案例-VIP 二.Z序控制三.层叠布局四.bilibili卡片案例五.list列表容器组件滚动条状态列表分割线 六.通用属性七.动画八.图形变换1.平移2.定位结合平移实现精准定位3.旋转和缩放 九.总结 一.定位 作用&#xff1a;改变组件位…

机器学习-------数据标准化

什么是归一化&#xff0c;它与标准化的区别是什么&#xff1f; 一 作用 在做训练时&#xff0c;需要先将特征值与标签标准化&#xff0c;可以防止梯度防炸和过拟合&#xff1b; 将标签标准化后&#xff0c;网络预测出的数据是符合标准正态分布的—StandarScaler()&#xff0c…

setImmediate() vs setTimeout() 在 JavaScript 中的区别

setImmediate() vs setTimeout() 在 JavaScript 中的区别 在 JavaScript 中&#xff0c;setImmediate() 和 setTimeout() 都用于调度任务&#xff0c;但它们的工作方式不同。 JavaScript 的异步特性 JavaScript 以其非阻塞、异步行为而闻名&#xff0c;尤其是在 Node.js 环境…

[000-002-01].第03节:Linux系统下Oracle的安装与使用

2.1.Docker安装Oracle 在CentOS7中使用Docker安装Oracle&#xff1a; 1.安装Docker,详细请参考&#xff1a;https://blog.csdn.net/weixin_43783284/article/details/1211403682.拉取镜像&#xff1a; docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g3.下载…

用Blender来烘培模型材质

通常我们在做三维设计&#xff0c;游戏开发的时候&#xff0c;经常需要从网上下载一些3D模型&#xff0c;这些模型采用的材质分辨率通常都不一样&#xff0c;而我们从性能考虑&#xff0c;需要对材质进行统一的处理&#xff0c;例如把材质都统一为2K的分辨率。 我们可以在Blen…