3.7作业

news2025/1/14 1:12:09

网络聊天室:

程序代码:

ser.c

#include <myhead.h>
//定义消息类型结构体
struct xiaoxi {
    char type;
    char name[20];
    char text[100];
};

int main(int argc, const char* argv[])
{
    // 创建套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd  == -1) 
	{
        perror("socket error");
        return -1;
    }
    // 设置端口快速重用
    int reuse = 1;
    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) 
	{
        perror("setsockopt error");
        return -1;
    }

    // 绑定
    // 定义地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[2]));
    sin.sin_addr.s_addr = inet_addr(argv[1]);
    
    if (bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1) 
	{
        perror("bind error\n");
        return -1;
    }

    // 设置监听
    if ((listen(sfd, 128)) == -1)
	{
        perror("listen error\n");
        return -1;
    }
    // 4接受请求
    // 存储客户端信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(atoi(argv[2]));
    cin.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t socklen = sizeof(cin);
    struct sockaddr_in arr_cin[1024];

    // 定义
    struct pollfd fds[1024];
    for (int i = 0; i < 1024; i++) 
	{
        fds[i].fd = -1;
        fds[i].events = POLLIN;
    }
    //将0和sfd放入数组
    fds[0].fd = 0;
    fds[1].fd = sfd;

    struct xiaoxi rec;//消息类型结构体变量
    char buf[128] = "";//接受消息的容器
    int newfd = -1; //存储文件描述符
    while (1) 
	{
        int res = poll(fds, 1024, -1);
        if (res < 0)
		{
            perror("poll error");
            return -1;
        }
		else if (res == 0)
		{
            printf("time out\n");
            return -1;
        }
        if (fds[0].revents == POLLIN)  //终端标准输入描述符
		{
            bzero(buf, sizeof(buf));
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf) - 1] = 0;
            for (int j = 4; j < 1024; j++)
			{
                send(fds[j].fd, buf, sizeof(buf), 0);
            }
        }
        if (fds[1].revents == POLLIN)//sfd
		{ 
            if ((newfd = accept(sfd, (struct sockaddr*)&cin, &socklen)) == -1) 
			{
                perror("accept error\n");
            }
            arr_cin[newfd] = cin; //将地址信息存入cin
            printf("------[%s:%d]连接成功------\n", inet_ntoa(arr_cin[newfd].sin_addr), htons(arr_cin[newfd].sin_port));
            fds[newfd].fd = newfd; //新生成的文件描述符放入数组
            fds[newfd].events = POLLIN;
        }
        for (int i = 4; i < 1024; i++) 
		{
            if (fds[i].fd < 0) 
			{
                continue;
            }
            if (fds[i].revents == POLLIN) 
			{
                bzero(buf, sizeof(buf));
                bzero(buf, sizeof(buf));
                int res = recv(fds[i].fd, &rec, sizeof(rec), 0); //接收客户端消息
                if (res == 0)
				{
                    close(fds[i].fd);
                    printf("------[%s:%d]断开连接------\n", inet_ntoa(arr_cin[fds[i].fd].sin_addr), htons(arr_cin[fds[i].fd].sin_port));
                    fds[i].fd = -1;
                    arr_cin[fds[i].fd].sin_addr.s_addr = 0;
                    arr_cin[fds[i].fd].sin_port = 0;
                    continue;
                }
                // 判断消息类型
                if (rec.type == 'L') // 登录消息
				{ 
                    for (int j = 4; j < 1024; j++)//发送给每个客户端
					{ 
                        if (j == i)
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "----------%s上线-----------", rec.name);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                } 
				else if (rec.type == 'C') // 聊天消息
				{ 
                    for (int j = 4; j < 1024; j++) 
					{
                        if (j == i) 
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "%s:%s", rec.name, rec.text);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                } 
				else 
				{                        //退出消息
                    //(rec.type == 'Q')
                    for (int j = 4; j < 1024; j++) 
					{
                        if (j == i)
						{
                            continue;
                        }
                        bzero(buf, sizeof(buf));
                        sprintf(buf, "-----------%s下线------------", rec.name);
                        send(fds[j].fd, buf, strlen(buf), 0);
                    }
                }
            }
        }
    }
    return 0;
}

cli.c

#include <myhead.h>

struct xiaoxi {
    char type;
    char name[20];
    char text[100];
};

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

    // 端口快速重用
    int reus = 1;
    if ((reus = setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reus, sizeof(reus))) == -1) 
	{
        perror("setsockopt error\n");
        return -1;
    }
	

    // 定义地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[2]));
    sin.sin_addr.s_addr = inet_addr(argv[1]);
   
    // 向客户端发送连接请求
    if (connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
	{
        perror("connect error");
        return -1;
    }


    struct xiaoxi sendi;

    char buf[100] = "";
    char nbuf[20] = "";

    
    struct pollfd fds[2];
    fds[0].fd=0;
    fds[0].events = POLLIN;

    fds[1].fd=cfd;
    fds[1].events = POLLIN;




    printf("请输入用户名:");
    fgets(nbuf,sizeof(nbuf),stdin);
    nbuf[strlen(nbuf)-1]=0;
    sendi.type = 'L';
    strcpy(sendi.name, nbuf);

    send(cfd, &sendi, sizeof(sendi), 0);
    while (1) 
	{
        int res = poll(fds,2,-1);           //阻塞检测
        if (fds[0].revents == POLLIN) 
        {
            bzero(buf, sizeof(buf));
            fgets(buf,sizeof(buf),stdin);
            buf[strlen(buf)-1]=0;
            sendi.type = 'C';    
            if(strcmp(buf,"quit")==0)
            {
                sendi.type = 'Q';
                sendto(cfd, &sendi, sizeof(sendi), 0, (struct sockaddr*)&sin, sizeof(sin));
                break;
            }
            strcpy(sendi.text,buf);
            sendto(cfd, &sendi, sizeof(sendi), 0, (struct sockaddr*)&sin, sizeof(sin));
        }
        if (fds[1].revents == POLLIN)
		{
            bzero(buf, sizeof(buf));
            int res = recv(cfd, buf, sizeof(buf), 0);
            printf("%s\n", buf);
            if (res == 0) 
			{
                printf("服务器下线\n");
                break;
            }
            
        }
    }
    close(cfd);
    return 0;
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1497204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flutter编译后的windows程序缺少msvcp140.dllvcruntime140.dllvcruntime140_1.dll解决办法

//就是很多博文中提到了三剑客 msvcp140.dll vcruntime140.dll vcruntime140_1.dll 1.没有vs环境的不要把生成的debug下的exe发给别人&#xff0c;会出现莫名其妙的问题。缺少各种DLL文件&#xff0c;我这边收集了上面三个的dll下载链接&#xff1a;flutterdll.rar - 蓝奏云 2…

【动态规划】【数论】【区间合并】3041. 修改数组后最大化数组中的连续元素数目

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 数论 区间合并 LeetCode3041. 修改数组后最大化数组中的连续元素数目 给你一个下标从 0 开始只包含 正 整数的数组 nums 。 一开始&#xff0c;你可以将数组中 任意数量 元素增加 至多 1 。 修改后&#xff0c;你可以从…

java网络编程 02 socket

01.socket定义 02.TCP编程 import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;public class clientSocket {public static void main(String[] args) throws IOException {//创建客户端socket&#xff0c;…

Get了!原来朋友圈定时发布如此简单!

你是不是也有这样的烦恼&#xff1f;微信号太多&#xff0c;有时候会顾不上发朋友圈&#xff1f; 别担心&#xff01;微信管理系统来帮你解决这个问题&#xff0c;实现朋友圈定时发布&#xff01;让我们一起来看看如何利用微信管理系统的强大功能来提升我们的社交媒体效率吧。…

请说明Vue中的解耦能力

Vue中的解耦能力是指在Vue框架中&#xff0c;我们能够有效地将代码分离成独立的组件或模块&#xff0c;使得这些组件之间的依赖关系减少&#xff0c;实现高内聚、低耦合的设计目标。利用Vue中的组件化开发&#xff0c;可以让不同的模块之间更容易地通信和协作&#xff0c;提高代…

echarts中toolbox 中文乱码问题

问题描述 本地引用的echarts源文件&#xff0c;页面其他部分编码显示正常&#xff0c;唯独toolbox鼠标悬停在上面时提示信息显示乱码。 如图所示&#xff1a; 尝试过的方法 使用sublime text 3&#xff0c;notepad&#xff0c;记事本更改文件编码为utf-8引入时&#xff0c;在sc…

短剧小程序:掌中剧院,随时演绎精彩

在快节奏的现代生活中&#xff0c;人们越来越追求高效与便捷。为了满足广大用户对短剧内容的热爱和追求&#xff0c;我们推出了全新的短剧小程序&#xff0c;让精彩剧情触手可及&#xff0c;随时随地为您带来欢乐与感动。 一、轻松点播&#xff0c;随享短剧魅力 通过短剧小程…

软件系统开发安全指南-word

应用系统设计安全主要涵盖以下几点&#xff1a; 1、应用系统架构安全设计 2、应用系统软件功能安全设计 3、应用系统存储安全设计 4、应用系统通讯安全设计 5、应用系统数据库安全设计 应用系统测试安全包含&#xff1a; 1、测试前置要求 2、测试方法及测试内容 3、测试环境及人…

10大AI工具

ChatGPT ChatGPT是由OpenAI开发的人工智能聊天机器人程序&#xff0c;全称为Chat Generative Pre-trained Transformer。它基于GPT-3.5架构&#xff0c;能够生成回答并根据聊天上下文进行互动。ChatGPT具备强大的对话能力&#xff0c;能在同一会话中回答上下文相关的问题&…

安卓简单登录

注意 有的朋友不知道登录咋写&#xff0c;这里我就简单给出相应代码&#xff0c;用的本地存储&#xff0c;没用网络请求&#xff0c;有需要可以替换成想要的&#xff0c;废话不多上代码 登录 import androidx.appcompat.app.AppCompatActivity;import android.content.Context…

JavaWeb----MySQL

一&#xff1a;JavaWeb相关介绍 Web&#xff1a;全球广域网&#xff0c;也称为万维网&#xff08;www&#xff09;&#xff0c;能够通过浏览器访问的网站 JavaWeb&#xff1a;是用Java技术来解决相关Web互联网领域的技术栈 JavaWeb流程 1.网页&#xff1a;展现数据 2.数据…

postman只读模式的解决办法

我大概是多次复制参数&#xff08;或是别的操作&#xff09;&#xff0c;进入了postman的只读模式。这时无法修改页面的传参&#xff0c;而且右上角的save按钮是灰色&#xff08;不可选&#xff09; 下面分享我的2种解决办法 第一种方法 在任务栏右键选中接口&#xff0c;选…

RUST 每日一省:发布到crates.io

github是开源代码分享的地方&#xff0c;rust的开源项目除了github&#xff0c;我们还可以将其发布到 crates.io 上&#xff0c;然后其它用户就可以使用cargo进行安装使用了。其实步骤很简单&#xff0c;只有三条命令了&#xff0c;我们一次来看一下。 1、cargo package 首先&a…

使用Navicat连接阿里云服务器上的MySQL数据库

打开navicat&#xff0c;连接如下&#xff1a; 服务器的默认密码是 root 连接时出现 使用 ls 查找 /etc/my.cnf ls /etc/my.cnf 用vi打开my.cnf&#xff1a; vi /etc/my.cnf看看是否有绑定本地回环地址的配置&#xff0c;如果有&#xff0c;注释掉下面这段文字&#xff1a;…

GitHub Desktop的常用操作【图形化】

文章目录 【1】仓库的创建和删除【2】文件操作【3】分支原理与分支操作1.分支创建2.分支合并 【4】标签 【1】仓库的创建和删除 在本地创建一个新的仓库&#xff1a; 然后输入仓库的名称&#xff0c;描述&#xff0c;并选择路径&#xff1a; 点击完后就发现我们的仓库创建好…

Anaconda的使用及spyder相关设置

Anaconda Anaconda是一个Python发行版&#xff0c;主要用于数据科学和机器学习领域。Anaconda集成了许多常用的数据科学工具和库&#xff0c;如NumPy、Pandas、Scikit-learn等&#xff0c;同时还包含了一个强大的包管理器conda和一个集成开发环境Spyder。Anaconda的目标是提供一…

鼠标光标选取文本、获取文本索引

1.效果图 这是在做一个字段分割的需求 2.思路 步骤一&#xff1a;通过document添加mouseup事件&#xff1b; 步骤二&#xff1a;通过window的getSelection()函数获取文本值&#xff1b; 步骤三&#xff1a;通过mouseup事件的event 类名来限制可截取元素的范围&#xff1b;…

论文解读:Meta-Baseline: Exploring Simple Meta-Learning for Few-Shot Learning

文章汇总 总体问题 通过对整体分类的训练(文章结构图中ClassifierBaseline)&#xff0c;即在整个标签集上进行分类&#xff0c;它可以得到与许多元学习算法相当甚至更好的嵌入。这两种工作之间的界限尚未得到充分的探索&#xff0c;元学习在少样本学习中的有效性仍然不清楚。…

【CSP】201403-3-命令行选项

CSP-201403-3-命令行选项 关键点&#xff1a;将整行字符串按空格分割 在解析命令行时&#xff0c;一个常见的需求是将整个命令行字符串分割成多个部分&#xff0c;通常以空格为分隔符。这些部分包括命令行工具的名称、选项&#xff08;可能带有前缀-或--&#xff09;和这些选项…

【Simulink系列】——控制系统仿真基础

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 一、控制系统基本概念 这里就不再介绍类似于开环系统、闭环系统等基本概念了&#xff01; 1、数学模型 控制系统的数学模型是指动态数学模型&#xff0c;大致…