2024-03-23 作业

news2024/11/18 21:38:09

网络聊天室 

运行代码:
main.c
#include "link.h"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
	if(argv[1]==NULL){
		printf("请输入IP地址\n");
		return 0;
	}
	//创建套接字文件
	int sfd = socket(AF_INET,SOCK_DGRAM,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;
	}
	//创建用户信息头结点
	usermsg_p H = node_head();

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port=htons(SER_PORT);
	sin.sin_addr.s_addr=inet_addr(argv[1]);

	if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
		perror("bind error");
		return -1;
	}
	H->cin=sin;
	//IO 多路复用
	struct pollfd pfd[2];
	pfd[0].fd = 0;
	pfd[0].events = POLLIN;
	pfd[1].fd = sfd;
	pfd[1].events=POLLIN;

	//接受用户信息所用的结构体
	struct sockaddr_in cin;
	socklen_t socklen = sizeof(cin);
	usermsg user_msg;
	usertext user_text;
	char buf[200]="";
	
	while(1){

		poll(pfd,2,-1);
		/***************输入**************************/
#if 1
		if(pfd[0].revents==POLLIN){
			//输出
			bzero(buf,sizeof(buf));
			fgets(buf,sizeof(buf)-1,stdin);
			buf[strlen(buf)-1]=0;
			ser_allput(H,sfd,buf);
		}
#endif
		/*******************输出*************************/
		if(pfd[1].revents==POLLIN){
			recvfrom(sfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&cin,&socklen);
			switch(user_text.type){
				//上线
			case 0:{
		
					   bzero(buf,sizeof(buf));
					   printf("[%s]登录成功\n",user_text.username);
					   sprintf(buf,"[%s]已上线",user_text.username);
					   ser_allput(H,sfd,buf); 
					   insert_usermsg(H,cin,user_text.username);
				   };break;
				   //转发
			case 1:{
					   	
					    bzero(buf,sizeof(buf));
						sprintf(buf,"[%s]:%s",user_text.username,user_text.text);
						printf("[%s]chat成功\n",user_text.username);
					    ser_output(H,sfd,buf,cin.sin_port); 
						break;
				   };
				   //下线
			case 2:{
					   bzero(buf,sizeof(buf));
					   tail_usermsg(H,cin.sin_port);
					   printf("[%s]已下线\n",user_text.username);
					   sprintf(buf,"[%s]已下线",user_text.username);
					   ser_allput(H,sfd,buf); 
				   };break;

			}
		}
		//输出

	}
	/********************************************/

 
	close(sfd);
	return 0;
}
link.c
#include "link.h"
usermsg_p node_head(){
	
	usermsg_p H=(usermsg_p)malloc(sizeof(usermsg));
	if(NULL==H){
		printf("创建失败\n");
		return NULL;
	}
	H->next=NULL;
	H->front=NULL;
	return H;
}
usermsg_p node_create(struct sockaddr_in cin,char *username){
	usermsg_p new =  (usermsg_p)malloc(sizeof(usermsg));
	if(new==NULL){
		printf("创建新节点失败\n");
		return NULL;
	}
	bzero(new->username,sizeof(new->username));
	new->next=NULL;
	new->front=NULL; 
	return new;
}
  
//插入用户信息 头插
void insert_usermsg(usermsg_p H,struct sockaddr_in cin,char *username){
	if(NULL==H){
		printf("头传入失败\n");
 		return;
	}

	usermsg_p new=node_create(cin,username);
	if(new==NULL){
		printf("创建新节点失败\n");
		return;
	}
	new->next=H->next;
	new->front = H;
	H->next = new;
	new->cin=cin;
	strcpy(new->username,username);
	
}
//用户下线,删除 判断条件 
void tail_usermsg(usermsg_p H,short int port){
	printf("%d %d\n",__LINE__,ntohs(port));
	if(NULL==H){
		printf("指针传入失败\n");
		return;
	}
	if(H->next==NULL){
		return;
	}
	usermsg_p p = H->next;
	while(p!=NULL){
		if(ntohs(port)==ntohs((p->cin).sin_port)){
		printf("%d %d\n",__LINE__,ntohs((p->cin).sin_port));
			p->front->next = p->next;
			if(p->next!=NULL)
				p->next->front = p->front;
			free(p);
			return;
		}
		p=p->next;
	}
	printf("没找到用户数据,删除失败\n");
}

//功能:转发
#if 1
void ser_output(usermsg_p H,int sfd,char *text,short int port){

	if(H==NULL){
		printf("%d link.c 传输失败\n",__LINE__);
		return;
	}
	usermsg_p p = H->next;
	while(p!=NULL){
		if(ntohs((p->cin).sin_port)==ntohs(port)){
			p=p->next;
			continue; 
		}
		sendto(sfd,text,strlen(text)+1,0,(struct sockaddr *)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
}

void ser_allput(usermsg_p H,int sfd,char *text){
	if(NULL==H){
		printf("%d H传入失败\n",__LINE__);
		return;
	}
	if(H->next==NULL){
		return;
	} 
	usermsg_p p = H->next;
	while(p!=NULL){
		sendto(sfd,text,strlen(text)+1,0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
}
#endif
//

link.h 
#ifndef __LINK_H__
#define __LINK_H__
#include<myhead.h>

typedef struct usermsg{
	
	char username[20];
	struct sockaddr_in cin;
	struct usermsg *next;
	struct usermsg *front;

}usermsg,*usermsg_p;

typedef struct usertext{

	char type; //客户端状态
	char username[20];
	char text[128];
	
}usertext,*usertext_p;
 
usermsg_p node_head();//创建头结点
usermsg_p node_create(struct sockaddr_in cin,char *username);//新节点、存放用户信息
void insert_usermsg(usermsg_p H,struct sockaddr_in cin,char *username);//插入用户信息
void tail_usermsg(usermsg_p H,short int port);//用户下线,删除
void ser_output(usermsg_p H,int sfd,char *text,short int port);
void ser_allput(usermsg_p H,int sfd,char *text);
#endif
客户端: 
#include<myhead.h>
struct usertext{
	char type;
	char username[20];
	char text[128];
};
int main(int argc, const char *argv[])
{
	if(argv[1]==NULL){
		printf("请输入IP地址\n");
		return 0;
	}
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1){
		perror("socket error");
		return -1;
	}
	//前摇
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	struct usertext user_text;

	char buf[200] = "";
	int port=0;
	user_text.type=0;

	printf("请输入用户名>>>");
	fgets(buf,sizeof(buf)-1,stdin);
	buf[strlen(buf)-1]=0;
	user_text.type=0;
	strcpy(user_text.username,buf);
	sin.sin_addr.s_addr = inet_addr(argv[1]);
	printf("请输入服务器端口>>>");
	scanf("%d",&port);
	sin.sin_port = htons(port);
	//发送连接请求
	sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));
	user_text.type=1;

	//IO多路复用 poll 
	struct pollfd pfd[2];
	pfd[0].fd = 0;
	pfd[0].events = POLLIN; 
	pfd[1].fd = cfd;
	pfd[1].events = POLLIN;
	int i = 0;	
	while(1){
		poll(pfd,2,-1); 
		if(pfd[0].revents==POLLIN){
			fgets(user_text.text,sizeof(user_text.text)-1,stdin);
			if(0==i){i++;continue;}
			user_text.text[strlen(user_text.text)-1]=0;
			if(strcmp(user_text.text,"quit")==0){
				user_text.type = 2;
				sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));	
				break;
			}
			sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));	
		}
		if(pfd[1].revents==POLLIN){
			recv(cfd,buf,sizeof(buf)-1,0);
			printf("%s\n",buf);
		}
	}
	close(cfd);

	return 0;
}
运行截图:

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

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

相关文章

【计算机网络】常见面试题汇总

文章目录 1.计算机网络基础1.1网络分层模型/OSI七层模型是什么&#xff1f;1.2TCP/IP四层模型是什么&#xff1f;每一层的作用&#xff1f;1.2.1TCP四层模型&#xff1f;1.2.2为什么网络要分层&#xff1f; 1.2常见网络协议1.2.1应用层常见的协议1.2.2网络层常见的协议 2.HTTP2…

MongoDB知识

1、部署MongoDB &#xff08;1&#xff09;new好一个mongo文件之后执行 &#xff08;出现mongodb.key&#xff09;记得放行端口 openssl rand -base64 666 > mongodb.key &#xff08;2&#xff09;放到一个docker-compose.yml之后docker-compose up -d执行 version: 3.…

数学(算法竞赛、蓝桥杯)--快速幂

1、B站视频链接&#xff1a;G01 快速幂_哔哩哔哩_bilibili 题目链接&#xff1a;P1226 【模板】快速幂 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <bits/stdc.h> using namespace std; typedef long long LL; int a,b,p; int quickpow(LL a,int n,int p){…

【wails】(10):研究go-llama.cpp项目,但是发现不支持最新的qwen大模型,可以运行llama-2-7b-chat

1&#xff0c;视频演示地址 2&#xff0c;项目地址go-llama.cpp 下载并进行编译&#xff1a; git clone --recurse-submodules https://github.com/go-skynet/go-llama.cpp cd go-llama.cpp make libbinding.a项目中还打了个补丁&#xff1a; 给 编译成功&#xff0c;虽然有…

力扣面试150 阶乘后的零 数论 找规律 质因数

Problem: 172. 阶乘后的零 思路 &#x1f468;‍&#x1f3eb; 大佬神解 一个数末尾有多少个 0 &#xff0c;取决于这个数 有多少个因子 10而 10 可以分解出质因子 2 和 5而在阶乘种&#xff0c;2 的倍数会比 5 的倍数多&#xff0c;换而言之&#xff0c;每一个 5 都会找到一…

vue3与Electron构建跨平台应用(webpack)

一、创建vue3项目 vue create vue3_webpack_electron 二、安装Electron npm install --save-dev electron Electron 三、vue add electron-builder vue add electron-builder

VMware中UbuntuServer扩展硬盘空间

VMware中UbuntuServer扩展硬盘空间 没有不可治愈的伤痛&#xff0c;没有不能结束的沉沦&#xff0c;所有失去的&#xff0c;会以另一种方式归来 ——【约翰-肖尔斯】 第一步 lxalxa:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS loop0 …

鸿蒙Harmony应用开发—ArkTS-像素单位

ArkUI为开发者提供4种像素单位&#xff0c;框架采用vp为基准数据单位。 说明&#xff1a; 本模块首批接口从API version 7开始支持&#xff0c;后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 名称描述px屏幕物理像素单位。vp屏幕密度相关像素&#xff0c;…

OpenCV学习笔记(十一)——利用Sobel算子计算梯度

Sobel算子是基于一阶导数的离散差分算子&#xff0c;其中Sobel对于像素值的变化是十分敏感的&#xff0c;在进行边缘检测的时候&#xff0c;Sobel算子常用于对周围像素的重要性进行检测。 Sobel算子包括检验水平方向的算子和检测竖直方向的算子 计算机梯度值的操作如下&#x…

XUbuntu22.04之安装Plantuml(二百二十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

微信小程序Skyline搜索框吸顶到navtab胶囊位置,丝滑Q弹动画

进入下面小程序可以体验效果&#xff1a; 基于官方原版demo加入了回弹动画 WXML: <scroll-viewclass"scroll-area"type"custom"scroll-yshow-scrollbar"{{false}}"worklet:onscrollend"handleScrollEnd"worklet:onscrollupdate&q…

【工具】cassetteai — 制作音乐就像现在写提示一样简单

Cassette 是一种人工智能驱动的音乐创作工具,使各种技能水平的用户都可以根据自己的特定需求和偏好生成高质量、免版税的音乐曲目。它基于基于潜在扩散 (LDM) 的机器学习模型,可以使用用户提供的文本描述来想象节拍。它具有易于使用的界面,用户可以输入各种参数,例如所需的…

Qt播放音乐代码示例

主界面 点击play按钮播放或暂停音乐&#xff0c;拖动进度条&#xff0c;音乐对应播放。 QWidget window;QPushButton* playButton new QPushButton("Play");// Qt 播放音乐// 创建 QMediaPlayer 对象QMediaPlayer* player new QMediaPlayer;// 指定音频文件的路径…

查立得php+mysql源码通用数据库配置教程

适用范围&#xff1a; 查分吧PHP多条件都输对版已有表万用查询系统 phpMySql已有数据表通用搜索可增删改查 查立得快搜系统(phpMysql) v20220208 查立得万能查&#xff08;phpmysql&#xff09; v20220512 及 各付费版 等几十款源码 数据库配置路径 数…

Redis的String类型为什么重新设计使用了SDS数据结构呢

Redis 选择重新设计其 String 类型的底层数据结构&#xff0c;采用 SDS&#xff08;Simple Dynamic String&#xff09;而不是直接使用 C 语言标准库提供的原生字符串&#xff08;char*&#xff09;的原因主要包括以下几点&#xff1a; O(1) 时间复杂度获取长度&#xff1a; 在…

SpringBoot健康监控

文章目录 1-SpringBoot2-监控-健康监控服务2-SpringBoot2-监控-Admin可视化 在Spring Boot中&#xff0c;可以通过Actuator模块实现应用程序的健康监控。Actuator是Spring Boot提供的一个用于监控和管理应用程序的模块&#xff0c;可以轻松地查看应用程序的运行状况、性能指标和…

部署prometheus 监控k8s集群

目录 1、主机清单 2、拉取镜像 3、服务安装 4、安装prometheus-operator 5、查看custom metrics api 6、获取prometheus端口 7、将 alertmanager-main 、grafana、prometheus-k8s的端口暴露出来 8、再次查看prometheus端口 9、浏览器访问IP&#xff1a;31940 部署k8集群…

创建vue3项目并集成cesium插件运行

创建vue3项目并集成cesium插件 一、vue项目创建 1、前期准备 node.js&npm或yarn 本地开发环境已经安装好。 参考安装 2、安装vue-cli&#xff0c;要求3以上版本 #先查看是否已经安装 vue -V#安装 npm install -g vue/cli4.5.17 示例&#xff1a;Idea工具 页面 Termin…

【物联网开源平台】tingsboard二次开发环境搭建+编译

文章目录 一&#xff0c;需要准备的环境二&#xff0c;获取tingsboard源码1.git拉取源码2.下载源码压缩包 三.新建仓库存放依赖文件四&#xff0c;编译五&#xff0c;遇到的错误 提示&#xff1a; 1.这篇只要准备两个环境&#xff0c;方法更简单&#xff01; 2.基于tingsboard …

CSS3新属性(学习笔记)

一、. 圆角 border-radius:; 可以取1-4个值&#xff08;规则同margin&#xff09; 可以取px和% 一般用像素&#xff0c;画圆的时候用百分比&#xff1a;border-radius:50%; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&q…