网络编程作业day5

news2024/11/19 7:36:31

将课堂上实现的模型(IO多路复用)重新自己实现一遍

服务器代码:

#include<myhead.h>
#define SER_IP "192.168.125.151"  //服务器IP
#define SER_PORT 8888            //服务器端口号

int main(int argc, const char *argv[])
{
    //创建用于监听的套接字
    int sfd = -1;
    sfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }   
    printf("sfd = %d\n", sfd);   
    //将端口号快速重用
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
    {
        perror("setsockopt error");
        return -1;
    }
    //2、绑定ip地址和端口号
    struct sockaddr_in sin;
    sin.sin_family =     AF_INET;    //地址族
    sin.sin_port =         htons(SER_PORT);    //端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP);  //IP地址
    if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1)
    {
        perror("bind error");
        return -1;
    }    
    //3、启动监听,允许客户端连接
    if(listen(sfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }       
    struct sockaddr_in cin;       //用于接收客户端地址信息结构体
    socklen_t socklen = sizeof(cin);     //用于接收客户端地址信息的大小
    int newfd;            
    char sbuf[128];        //从键盘上输入数据

    //1、创建文件描述符容器
    fd_set readfds, tempfds;
    //2、清空容器内容
    FD_ZERO(&readfds);
    //3、将sfd和0号文件描述符放入容器中
    FD_SET(0, &readfds);
    FD_SET(sfd, &readfds);   
    int maxfd = sfd;           //存放容器中最大的文件描述符的值
    struct sockaddr_in cin_arr[1024];    //存放客户端对应的地址信息
    while(1)
    {
        tempfds = readfds;      
        int res = select(maxfd+1, &tempfds, NULL, NULL, NULL);  //阻塞等待集合中事件产生
        if(res == -1)
        {
            perror("select error");
            return -1;
        }else if(res == 0)
        {
            printf("time out\n");
            return -1;
        }
        //遍历所有的容器中的文件描述符
        for(int i=0; i<=maxfd; i++)
        {
            //判断当前的文件描述符是否在tempfds中,如果不在,直接下一个
            if(!FD_ISSET(i, &tempfds))
            {
                continue;
            }
            if(i == sfd)       
            {
                newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
                if(newfd == -1)
                {
                    perror("accept error");
                    return -1;
                }
                printf("newfd = %d 您有新的客户已经上线\n", newfd);
                printf("客户端IP:%s, 端口号为:%d\n", inet_ntoa(cin.sin_addr),  ntohs(cin.sin_port));
                //将客户端文件描述符放入到集合中
                FD_SET(newfd, &readfds);
                cin_arr[newfd] = cin;         //将新的客户端地址信息放入容器
                //更新maxfd
                if(newfd > maxfd)
                {
                    maxfd = newfd;
                }
            }
			else if(i==0) 
            {
                //从键盘输入数据
                fgets(sbuf, sizeof(sbuf), stdin);
                sbuf[strlen(sbuf)-1] = 0;
                printf("触发了键盘输入事件:%s\n", sbuf);
                //将消息发给每一个客户端
                for(int k=4; k<=maxfd; k++)
                {
                    send(k, sbuf, strlen(sbuf), 0);   
                }
            }
			else
            {
                //5、通信套接字与客户端进行数据收发
                char rbuf[128];
                //清空容器
                bzero(rbuf, sizeof(rbuf));
                //从套接字中读取数据
                int res = recv(i, rbuf, sizeof(rbuf), 0);
                if(res == 0)
                {
                    printf("客户端已经下线\n");
                    //关闭套接字
                    close(i);
                    //将当前文件描述符从容器中移除
                    FD_CLR(i, &readfds);
                    //更新maxfd
                    for(int j=maxfd; j>=0; j--)
                    {
                        if(FD_ISSET(j, &readfds))
                        {
                            maxfd = j;
                            break;
                        }
                    }
                    continue;
                }
                printf("[%s:%d] :%s\n",inet_ntoa(cin_arr[i].sin_addr),ntohs(cin_arr[i].sin_port), rbuf);
                //回复消息
                strcat(rbuf, "*_*");
                send(i, rbuf, strlen(rbuf), 0);
            }
        }
    }
	//关闭套接字
    close(sfd);
    return 0;
}

 客户端代码:

#include <myhead.h>
#define SER_IP "192.168.125.151"     //服务器ip地址
#define SER_PORT 8888              //服务器端口号
#define CLI_IP "192.168.125.151"   //客户端ip地址
#define CLI_PORT  3434            //客户端端口号
int main(int argc, const char *argv[])
{
	//创建套接字
	int cfd = socket(AF_INET, SOCK_STREAM, 0);
	if(cfd==-1)
	{
		perror("socket error");
		return -1;
	}
	printf("cfd = %d\n", cfd);          

	//连接服务器
	//填充要连接的服务器地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;   //地址族
	sin.sin_port =     htons(SER_PORT);   //端口号
	sin.sin_addr.s_addr = inet_addr(SER_IP);   //ip地址
	if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin))==-1)
	{
		perror("connect error");
		return -1;
	}
	printf("connect success\n");

	//使用poll完成客户端的读写操作并发执行
	//1、定义一个pollfd数组
	struct pollfd pfd[2];
	pfd[0].fd = 0;         //检测0号文件描述符
	pfd[0].events = POLLIN;   //检测0号文件描述符的读操作
	pfd[1].fd = cfd;          //检测cfd文件描述符
	pfd[1].events = POLLIN;  //检测cfd中的读操作

	//数据收发
	char wbuf[128] = "";
	while(1)
	{
		int res = poll(pfd, 2, -1);   //阻塞检测集合中是否有事件产生
		if(res == -1)
		{
			perror("poll error");
			return -1;
		}else if(poll == 0)
		{
			printf("time out\n");
			return -1;
		}

		if(pfd[0].revents == POLLIN)              //表示0号文件描述符事件产生
		{

			//清空数据
			bzero(wbuf, sizeof(wbuf));
			printf("请输入:");
			fgets(wbuf, sizeof(wbuf),stdin); 
			wbuf[strlen(wbuf)-1]='\0';
			//将数据发送给服务器
			send(cfd, wbuf, strlen(wbuf), 0);
			printf("发送成功\n");                       
			//判断发送的数据
			if(strcmp(wbuf, "quit") == 0)
			{
				break;
			}
		}
		if(pfd[1].revents == POLLIN) 
		{
			//接收服务器发来的消息
			//清空数据
			bzero(wbuf, sizeof(wbuf));
			recv(cfd, wbuf, sizeof(wbuf), 0); 
			printf("收到消息为:%s\n", wbuf);
		}
	}
	//关闭套接字
	close(cfd);
	return 0;
}

 

思维导图:

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

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

相关文章

首尔之春在线资源最新电影1080p高清

打开下面这个链接就可以看到 首尔之春在线资源最新电影1080p高清 如果链接打不开&#xff0c;就复制下面的网址到浏览器打开 https://www.zhufaka.cn/liebiao/A09504AE3BF8BD06 用阿里云盘下载&#xff0c;下载完成之后&#xff0c;用迅雷播放 首尔之春在线资源最新电影10…

JAVA SE 2.基本语法

1.Java的基本语法 1.基本格式 // 类的修饰包括&#xff1a;public&#xff0c;abstract&#xff0c;final 修饰符 class 类名{程序代码 } 例: public class Test{public static void main(String[] args){System.out.println("hello " "world");} }语法说明…

蓝桥杯——123

123 二分等差数列求和前缀和数组 题目分析 连续一段的和我们想到了前缀和&#xff0c;但是这里的l和r的范围为1e12&#xff0c;明显不能用O(n)的时间复杂度去求前缀和。那么我们开始观察序列的特点&#xff0c;可以按照等差数列对序列进行分块。如上图&#xff0c;在求前10个…

一台服务器,最大支持的TCP连接数是多少?

一个服务端进程最大能支持多少条 TCP 连接&#xff1f; 一台服务器最大能支持多少条 TCP 连接&#xff1f; 一、原理 TCP 四元组的信息&#xff1a;源IP、源端口、目标IP、目标端口。 一个服务端进程最大能支持的 TCP 连接个数的计算公式&#xff1a;最大tcp连接数客户端的IP…

Nodejs 第四十六章(redis持久化)

redis持久化 Redis提供两种持久化方式&#xff1a; RDB&#xff08;Redis Database&#xff09;持久化&#xff1a;RDB是一种快照的形式&#xff0c;它会将内存中的数据定期保存到磁盘上。可以通过配置Redis服务器&#xff0c;设置自动触发RDB快照的条件&#xff0c;比如在指…

达梦数据库QA(一):用户赋予系统权限 Any 时报“授权者没有此授权权限”

问题描述 达梦数据库&#xff0c;给用户赋予系统权限 Any 时报“授权者没有此授权权限” 解决方案 方法 1&#xff1a;在 dm.ini 文件中修改参数 ENABLE_DDL_ANY_PRIV 为 1。 方法 2&#xff1a; 通过以下语句修改参数 ENABLE_DDL_ANY_PRIV。 sp_set_para_value(1,‘ENABLE…

matplotlib——直方图(python)

需求 假设你获取了250部电影的时长&#xff0c;希望统计出这些电影时长的分布状态等信息。 代码 from matplotlib import pyplot as plt import matplotlibmatplotlib.rc("font",family"FangSong")# 初始化数据 a[131, 98, 125, 131, 124, 139, 131, 1…

如何使用公网地址远程访问内网Nacos UI界面查看注册服务

文章目录 1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Plik Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a;持久化…

day58 异常 IO流

异常 1异常处理机制 编译时错误 运行时错误 代码逻辑错误 2异常类结构图 java.lang.Throwable 所有异常的父类 只有它能剖出异常 java.lang.Error: extends Throwable 程序中的硬件严重问题不需要处理 java.lang.Exception extends Throwable 异常 指出要捕获的处理条件 3异常…

Licky‘s Escape 现已在苹果应用商店上线!

Pixelcraft 隆重推出 Aavegotchi 的首款手机游戏 —— Lickys Escape&#xff01; Lickys_Escape_Launch1_2024--1- 与 Licky 一起潜入 Gotchiverse吧&#xff01;Licky是一只憨厚但勇敢的Lickquidator&#xff0c;但它的任务出了差错。被一群卑鄙的 Gotchis 抓走后&#xff0c…

户外、春衣、养发……阿里妈妈经营指南揭秘38消费热点

在春天这个万象更新的季节&#xff0c;春天生意也在升温。 内容平台上&#xff0c;#成都醉美樱花季 #春天穿什么 互动增长率分别达到了156倍、252倍&#xff1b;#初春氛围感穿搭 #春游记 的互动增长率分别达到了77倍、24倍……“赏花”“穿搭”“居家锻炼”等和春天有关的消费…

计算机组成原理之机器:计算机系统的基本概念

计算机组成原理之机器 笔记来源&#xff1a;哈尔滨工业大学计算机组成原理&#xff08;哈工大刘宏伟&#xff09; Chapter1&#xff1a;计算机系统的基本概念 1.1 计算机系统简介 从物理构成的角度对计算机系统分层 计算机组成原理主要关注微体系结构&#xff08;Mirco-arc…

2024年3月6日 十二生肖 今日运势

小运播报&#xff1a;2024年3月6日&#xff0c;星期三&#xff0c;农历正月廿六 &#xff08;甲辰年丁卯月己巳日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;牛、猴、鸡 需要注意&#xff1a;鼠、虎、猪 喜神方位&#xff1a;东北方 财神方位&#xff1a;正…

知识图谱辅助的个性化推荐系统

知识图谱辅助的个性化推荐系统 将从下面4个方面展开&#xff1a; 推荐系统的基础知识知识图谱辅助的推荐方法介绍基于embedding的知识图谱推荐方法混合型知识图谱推荐方法 推荐系统的基础知识 1、什么是推荐系统 在当前互联网时代&#xff0c;推荐系统是所有面向用户的互联…

《剑指offer》14--剪绳子(整数拆分)[C++]

目录 题目描述 贪心算法 输出结果 题目描述 把一根绳子剪成多段&#xff0c;并且使得每段的长度乘积最大。 给定一个正整数 n&#xff0c;将其拆分为至少两个正整数的和&#xff0c;并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输出: 1 解释:…

Java基于SpringBoot的在线视频教育平台的设计与实现论文

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线视频教育平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了在线视频教育平台&#xff0c;它彻底改变了过…

Vue基础篇

Vue Vue是一套用于构建用户界面的渐进式JavaScript框架 什么是渐进式? Vue可以自底向上逐层地应用; 当构建简单应用时, 只需一个轻量小巧的核心库; 当构建复杂应用时, 可以引入各式各样的Vue插件 Vue具有以下特点: 采用组件化模式, 提高代码复用率且让代码更好维护 声明式编…

Claude3发布,ChatGPT-4 跌下神坛!兄弟相残?

就在3月5号凌晨&#xff0c;大家还在睡梦中的时候&#xff0c;Anthropic在X上低调的发布了Claude3&#xff0c;没有华丽的辞藻&#xff0c;没有大篇幅的介绍&#xff0c;只是简单的发了个帖子...... 几行简单的文字&#xff0c;浓缩着其一年多来的努力~ 真是让人不禁感叹&…

【STM32F103】WDG看门狗

本系列在之前介绍时钟树的文章中有稍微提一下看门狗WDG&#xff08;Watch Door Dog&#xff09;。 简单来说&#xff0c;可以当成是一个计数器&#xff0c;一旦这个计数器溢出则单片机复位。因为我们需要每隔一段时间就把这个计数器的值清零&#xff08;喂狗&#xff09;。 I…

【主题广范|见刊快】2024年可再生能源与智能电网国际学术会议(ICRESG 2024)

【主题广范|见刊快】2024年可再生能源与智能电网国际学术会议(ICRESG 2024) 2024 International Conference Renewable Energy and Smart Grid 本次会议汇聚了来自全球各地的专家学者&#xff0c;共同探讨可再生能源与智能电网领域的最新研究成果、技术进展和未来发展趋势。会…