HQYJ 2024-3-14 作业

news2024/11/29 11:21:44

 TCP通信三次握手和四次挥手:

并行和并发的区别:并发是单核处理器处理多个线程任务,并行是多核处理器同时处理多个线程任务。并发过程中会抢占CPU资源,轮流使用;并行过程不会抢占CPU资源。

阻塞IO和非阻塞IO:阻塞IO会等待事件的产生,如果事件没有发生,则会一直阻塞并等待,不会执行后面的任务。非阻塞IO如果事件没有发生,会立即返回,继续执行后面的任务。

同步和异步的区别:同步表示任务有顺序的执行,并且一个任务需要等上一个任务执行完才可以被允许执行;异步表示多个任务执行没有先后,可以并发执行;

IO多路复用的原理:遇到多个阻塞时,往往其中一个阻塞住了另一个会因为前面的阻塞而执行不了,所以多路复用的原理可以将多个阻塞任务的文件描述符统一放在一个检测的容器中,用一个阻塞函数去管理,当有一个或者多个文件描述符所对应的事件产生就会解除阻塞,去执行相应的函数。

广播的相关内容:广播地址=网络号+全为1的主机号,是一对多的通信,使用UDP实现;对发射端套接字设置成允许广播,所以的接收端都会接收到消息,发送端类似于UDP的客户端,接收端类似于UDP的服务器端。

组播的相关内容:组播地址是D类网络地址,需要对接收端设置允许多播组属性,也是一对多的通信,使用UDP实现;发送端类似于UDP的客户端,接收端类似于UDP的服务器端。

在使用套接字通信时一定不需要绑定操作吗?不一定,对于报式域套接字如果不绑定的话,系统不会自动绑定,当服务器发送数据时会因为客户端没有绑定路径会导致发送错误

进程通信方式:信号,无名管道,有名管道,共享内存,消息队列,信号灯集,套接字

线程的同步互斥机制:多个线程是共享的是进程资源,当一个线程去执行任务时,会因为时间片轮询到下一个线程,另一个线程会继续在共享的进程资源里执行程序,可能会导致上一个线程执行信息的修改而导致错误,为了防止这种竞态现象,引出互斥机制,例如互斥锁,线程也可以有顺序的执行完程序后继续到下一个线程执行,就引出了同步机制,例如信号量和条件变量。

1> 将白天课堂代码重新实现一遍:

select实现的TCP并发服务器

select实现的TCP客户端

#define SER_IP "192.168.117.2"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
	//IO多路复用服务器端
	int sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd==-1)
	{
		perror("socket error");
		return -1;
	}
	printf("socket success\n");

	//端口号复用
	int reuse = 1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
	{
		perror("setsockopt error");
		return -1;
	}
	//绑定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);

	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind error");
		return -1;
	}
	printf("bind success\n");

	//开启被动监听
	if(listen(sfd,128)==-1)
	{
		perror("listen error");
		return -1;
	}
	printf("listen success\n");
	//接受客户端的信息
	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);

	fd_set readfds,tempfds;
	FD_ZERO(&readfds);
	FD_SET(0,&readfds);
	FD_SET(sfd,&readfds);
	int maxfd = sfd+1;
	char sbuf[128] =  "";
	struct sockaddr_in cin_arr[1024];
	int newfd = -1;
	
	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++)
		{
			if(!FD_ISSET(i,&tempfds))
			{
				continue;
			}
			if(sfd==i)
			{
				newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
				if(newfd == -1)
				{
					perror("accept error");
					return -1;
				}
				printf("[%s %d]:发送连接请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
				cin_arr[newfd] = cin;
				FD_SET(newfd,&readfds);
				if(newfd>maxfd)
				{
					maxfd = newfd;
				}

			}else if(0==i)
			{
				fgets(sbuf,sizeof(sbuf),stdin);
				sbuf[strlen(sbuf)-1]=0;
				printf("触发键盘事件%s\n",sbuf);

				//将该消息发送给所有客户端
				for(int j=4;j<=maxfd;j++)
				{
					send(j,sbuf,sizeof(sbuf),0);
				}
				printf("发送成功\n");
			}
			else
			{
				char rbuf[128]="";
				bzero(rbuf,sizeof(rbuf));
				int res = recv(i,rbuf,sizeof(rbuf)-1,0);
				if(res == 0)
				{
					printf("客户端已下线\n");
					close(i);
					FD_CLR(i,&tempfds);
					for(int k=maxfd;k>=0;k--)
					{
						if(FD_ISSET(i,&tempfds))
						{
							maxfd=k;
							break;
						}
						continue;
					}
				}

				printf("[%s %d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);
				//加个笑脸还回去
				strcat(rbuf,"^0^");
				send(i,rbuf,sizeof(rbuf),0);
				printf("发送成功\n");

			}
		}
	

	}


	close(sfd);



	return 0;
}
#include<myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.117.2"
#define CLI_PORT 9999
#define CLI_IP "192.168.117.2"



int main(int argc, const char *argv[])
{
    //1、创建用于连接的客户端套接字
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success cfd = %d\n", cfd);        //3

    //设置端口号快速重用
    int reuse = 1;
    if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) ==-1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("端口号快速重用成功\n");
    
    //2、绑定端口号和ip地址(非必须)
    //2.1 填充客户端地址信息结构体
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);

    //2.2 绑定端口号和IP
    if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");
    
    
    //3、连接服务器
    //3.1 填充要连接服务器的地址信息结构体
    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地址

    //3.2 连接服务器
    if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("连接成功!\n");    
    //4、收发数据
    char buf[128] = "";

	//select
	fd_set readfds,tempfds;
	FD_ZERO(&readfds);
	FD_ZERO(&tempfds);
	FD_SET(cfd,&readfds);
	FD_SET(0,&readfds);
	int maxfd = cfd;

    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++)
		{
			if(!FD_ISSET(i,&tempfds))
			{
				continue;
			}
			if(0==i)
			{
				fgets(buf,sizeof(buf),stdin);
				buf[strlen(buf)-1]=0;
				send(cfd,buf,sizeof(buf)-1,0);
				printf("向服务器发送消息:%s\n",buf);
			}
			else if(i==cfd)
			{
				bzero(buf,sizeof(buf));
				int ret = recv(cfd,buf,sizeof(buf),0);
				printf("666\n");
				if(ret == 0)
				{
					printf("客户端下线\n");
					close(i);
					FD_CLR(i,&readfds);
					for(int j = maxfd;j>=0;j--)
					{
						if(!FD_ISSET(j,&readfds))
						{
							maxfd=j;
							break;
						}
						
					}
					return 0;
				}
				else
				{
					printf("接收的消息%s\n",buf);
				}


				
			}
		}
	}
/*
        printf("请输入>>>");
        fgets(wbuf, sizeof(wbuf), stdin);    //从终端上获取一个字符串
        wbuf[strlen(wbuf)-1] = '\0';      //将换行换成 '\0'

        //判断输入的字符串值
        if(strcmp(wbuf, "quit") ==0)
        {
            break;
        }

        //将数据发送给服务器
        send(cfd, wbuf, strlen(wbuf), 0);

        //将字符数组清空
        bzero(wbuf, sizeof(wbuf));
        recv(cfd, wbuf, sizeof(wbuf)-1, 0);
        printf("收到服务器消息为:%s\n", wbuf);
    }
    */
    //5、关闭套接字
    close(cfd);

    return 0;
}

 

 

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

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

相关文章

HarmonyOS开发:超详细介绍如何开源静态共享包,实现远程依赖

前言 当我们开发了一个独立的功能&#xff0c;想让他人进行使用&#xff0c;一般的方式就是开源出去&#xff0c;有源码的方式&#xff0c;也有文件包的形式&#xff0c;当然了也有远程依赖的方式&#xff0c;比如在Android中&#xff0c;我们可以提供源码&#xff0c;也可以打…

开源离线语音识别输入工具CapsWriter v1.0——支持无限时长语音、音视频文件转录字幕。

分享一款开源离线语音识别输入工具&#xff0c;支持无限时长语音、音视频文件转录字幕。 软件简介&#xff1a; CapsWriter是一款免费开源且可完全离线识别的语音输入工具&#xff0c;无需担心因在线版本识别带来的各种隐私泄露问题。支持win7及以上的系统&#xff0c;已经更…

华为中心AP 配置入侵防御实验

配置入侵防御示例 组网图形 图1 入侵防御组网图 组网需求配置思路操作步骤中心AP的配置文件 组网需求 如图1所示&#xff0c;某企业部署了WLAN网络&#xff0c;内网用户可以访问Internet的Web服务器。现需要在中心AP上配置入侵防御功能&#xff0c;具体要求如下&#xff1a; 保…

打印机怎么扫描文件到电脑?正确步骤在这里

在现代办公和生活中&#xff0c;打印机不再仅仅是用于输出纸质文件的工具&#xff0c;它还充当了功能强大的扫描仪&#xff0c;使我们能够方便地将纸质文件数字化并存储到电脑中。 如果您正在寻找如何正确将打印机用作扫描仪&#xff0c;以便轻松地将文件传输到电脑中&#xf…

【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024)

【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024) 大会主题: (主题包括但不限于, 更多主题请咨询会务组苏老师) 区块链&#xff1a; 区块链技术和系统 分布式一致性算法和协议 块链性能 信息储存系统 区块链可扩展性 区块…

智能合约语言(eDSL)—— 使用rust实现eDSL的原理

为理解rust变成eDSL的实现原理&#xff0c;我们需要简单了解元编程与宏的概念,元编程被描述成一种计算机程序可以将代码看待成数据的能力&#xff0c;使用元编程技术编写的程序能够像普通程序在运行时更新、替换变量那样操作更新、替换代码。宏在 Rust 语言中是一种功能&#x…

【QT+QGIS跨平台编译】之八十四:【QGIS_Gui跨平台编译】—【错误处理:未实例化QgsMapLayer - QgsHighlight】

文章目录 一、未实例化QgsMapLayer二、错误处理 一、未实例化QgsMapLayer 报错信息&#xff1a; 二、错误处理 第31行修改为&#xff1a; #include "qgsmaplayer.h"

【Web技术应用基础】HTML(2)——文本练习

题目1&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>HTML链接</title><meta name"description" content"HTML链接知识讲解"><meta name"keywords" content&qu…

(undone) 斯坦福机器学习 讨论课4 (分类器评估指标 TODO:暂时不知道内容是啥)

从标题来看这堂课跟评估指标有关&#xff0c;而且是专门针对分类器的评估指标 如下图&#xff0c;解释了 “为什么 metrics 很重要” 1.训练目标 (成本函数) 仅仅是现实世界目标的一个代理 (proxy) 2.理想的训练目标应该是指标 metric&#xff0c;但这并不总是可能的。metric…

Stability AI 3D:开创3D视觉技术新篇章,提升多视角连贯性与生成质量

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

ASPICE规范之系统追溯矩阵

系统追溯矩阵的需求来自 ISO26262 举例在描述系统追溯矩阵时&#xff1a;客户需求->系统需求&#xff1b;系统需求->客户需求&#xff1b;系统需求->软件需求&#xff1b;系统需求->硬件需求

有实际意义的伦敦金交易策略参考

一谈起有实际意义的伦敦金交易策略参考&#xff0c;很多人以为是讨论的是什么飞天遁地的技术&#xff0c;其实这些都是没有实际意义。对普通投资者来说&#xff0c;什么才是有实际意义的呢&#xff1f;那就是生存。要讨论实际有意义的伦敦金交易策略参考&#xff0c;就是投资者…

【计算机网络_网络层】IP协议

文章目录 1. IP的基本概念1.1 什么是IP协议1.2 为什么要有IP协议 2. IP的协议格式3. 网段划分&#xff08;重要&#xff09;3.1 为什么要进行网段划分3.2 网段划分的规则3.2.1 古老的划分方案3.2.2 现代的划分方案 4. 特殊的IP地址5. 解决IP地址的数量限制问题6. 私有IP和公网I…

【视频异常检测】Real-world Anomaly Detection in Surveillance Videos 论文阅读

Real-world Anomaly Detection in Surveillance Videos 论文阅读 Abstract1. Introduction2. Related Work3. Proposed Anomaly Detection Method3.1. Multiple Instance Learning3.2. Deep MIL Ranking Model 4. Dataset4.1. Previous datasets4.2. Our dataset 5. Experiment…

java8:LinkedList的实现原理

概述 先来看看源码中的这一段注释&#xff0c;我们先尝试从中提取一些信息&#xff1a; Doubly-linked list implementation of the List and Deque interfaces. Implements all optional list operations, and permits all elements (including null).All of the operations …

【Linux(1)】Linux的一些基本指令(补充上一篇)

思维导图 学习内容 通过上面的学习目标&#xff0c;我们可以列出要学习的内容&#xff1a; linux的一些指令&#xff1a;cd mkdir cp touch which rm cat alias 一些基本的概念&#xff1a;指令的概念&#xff0c;用户家目录是什么...... 一、Linux的一些指令 1.1 重新认识…

【SpringSecurity】十三、基于Session实现授权认证

文章目录 1、基于session的认证2、Demosession实现认证session实现授权 1、基于session的认证 流程&#xff1a; 用户认证成功后&#xff0c;服务端生成用户数据保存在session中服务端返回给客户端session id (sid&#xff09;&#xff0c;被客户端存到自己的cookie中客户端下…

信息发布系统

特色功能 画布功能---可任意拖动各控件的播放位置及大小&#xff0c;可任意选择屏幕背景色或添加背景图 同步联屏---毫秒级同步功能 视频切换无黑屏 触摸查询系统 会议预定系统 终端显示-会议综合屏 终端显示-会议预定屏 终端显示-移动端 广告发布系统 硬件产品-智能终端 硬件…

[uni-app] uni.createAnimation动画在APP端无效问题记录

文章目录 uni.createAnimation动画描述动画代码templatejs部分 问题原因改进方案template js部分改动git 改进截图 uni.createAnimation 动画描述 实现一个以左上角为锚点,以Z轴做平面抬起及落下的动画效果 动画代码 template <image v-if"showHot(item.cname)&quo…

查找众数及中位数 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 众数是指一组数据中出现次数量多的那个数&#xff0c;众数可以是多个。 中位数只是指把一组数据从小到大排列&#xff0c;最中间的那个数&#xff0c;如果这组数…