基于UDP网络聊天室OICQ

news/2024/5/18 12:07:39 标签: 网络, udp, 网络协议

Linux系统 + Gcc + Gdb + makefile

实现局域网OICQ程序设计,包括客户端和服务端。

客户端描述:客户端运行开始出现登陆界面。与服务端进行连接,连接后把账号信息发送给服务端,服务端验证后,把确认结果通知客户端。如果通过验证,客户端从服务端接收其他在线客户端信息并把这些客户信息显示给用户。用户可以选择客户并与之进行信息交流。即发送消息和接受消息。并把结果显示给用户。

服务端功能描述:服务端启动后,等待客户端连接。接受客户端发送过来的账号信息。进行验证。并把验证的结果返回给客户端。如果验证通过,记录客户端的信息。并把该客户端的记录的信息发送给其他的客户端,也把其他的在线用户发送给该用户,实现整个网络内的在线客户信息的同步。接受客户端的断开连接的请求。服务端断开连接,删除记录并把结果发送给其他的客户端。

Sock编程

根据配置文件信息启动服务端程序,监听端口,等待客户端连接。完成客户端于服务端简单的tcp连接。使用I/O复用机制完成客户端与服务端之间的一对多的连接。服务端记录每个客户端的基本信息:每个客户端的IP、端口等基本信息。使用链表记录保存这些信息。

相关代码参考

客户端:

#include <myhead.h>

typedef struct
{
	char type;
	char name[20];
	char text[128];
}msg_t;
//定义传送消息的结构体
int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("请输入服务器IP和端口号!\n");
		return -1;
	}
//提醒输入IP和端口号
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1)
	{
		perror("socket error");
		return -1;
	}
//创建套接字用于通信
	msg_t msg;
	char name[20] = "";
	printf("请输入用户名>>");
	scanf("%s",msg.name);
	getchar();
//输入名字
	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]);
//定义发送的服务器结构体
	char buf[129] = "";
	char rbuf[128] = "";

	bzero(buf,sizeof(buf));
	msg.type = 'L';
	sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
//发送登录信息结构体
	struct pollfd fds[2];
	fds[0].fd = 0;
	fds[0].events = POLLIN;

	fds[1].fd = cfd;
	fds[1].events = POLLIN;
	int res = 0;
//用poll函数多路复用
	while(1)
	{
		res = poll(fds,2,-1);
		if(res == -1)
		{
			perror("poll error");
			return -1;
		}
		else if(res == 0)
		{
			printf("time out\n");
			return -1;
		}

		bzero(buf,sizeof(buf));
		bzero(rbuf,sizeof(rbuf));

		if(fds[1].revents == POLLIN)
		{
			recvfrom(cfd,rbuf,sizeof(rbuf),0,NULL,NULL);
			printf("%s\n",rbuf);
		}

		if(fds[0].revents == POLLIN)
		{
			fgets(msg.text,sizeof(msg.text),stdin);
			msg.text[strlen(msg.text)-1]='\0';

			if(strcmp(msg.text,"quit")==0)
			{
				msg.type = 'Q';
				sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
				goto A;
			}
			msg.type = 'C';
			sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
		}
	}
A:
	close(cfd);
	return 0;
}

服务端:

#include <myhead.h>
typedef struct group
{
	char type;
	char name[20];
	char text[128];
}msg_t;
//创建信息结构体
typedef struct Node
{
	int PORT;
	struct Node* next;
}*Linklist;
//创建链表数据域的结构体
Linklist create_node()
{
	Linklist s=(Linklist)malloc(sizeof(struct Node));
	if(NULL == s)
		return NULL;
	s->PORT =0;
	s->next =NULL;
	return s;
}
//创建链表节点
Linklist insert_rear(Linklist head,int element)
{
	Linklist s=create_node();
	s->PORT=element;

	if(NULL == head)
	{
		head = s;
		return head;
	}
	Linklist p = head;
	while(p->next != NULL)
	{
		p=p->next;
	}
	p->next = s;
	return head;
}
//链表的头删

int lenth(Linklist head)
{
	if(head == NULL)
		return 0;
	int count=0;
	Linklist p=head;
	while(p!=NULL)
	{
		count++;
		p=p->next;
	}
	free(p);
	p=NULL;
	return count;
}
//链表求长度
int find_element(Linklist head,int element)
{
	Linklist p=head;
	for(int i=0;i<lenth(head);i++)
	{
		if(p->PORT == element)
			return i;
		p=p->next;
	}
}
//链表的按照元素查找
Linklist link_del_head(Linklist head)
{
	if(head->next == NULL)
	{
		free(head);head=NULL;
		return head;
	}
	Linklist del=head->next;
	head->PORT=del->PORT;
	head->next=del->next;
	free(del);del=NULL;
	return head;
}
//链表的头删
Linklist link_del_rear(Linklist head)
{
	if(head->next == NULL)
	{
		free(head);
		head = NULL;
		return head;
	}
	Linklist del=head;
	while(del->next->next!=NULL)
	{
		del=del->next;
	}
	free(del->next);
	del->next=NULL;
	return head;
}
//链表的尾删
Linklist link_del_pos(Linklist head,int pos)
{
	if(pos == lenth(head)-1)
	{
		head = link_del_rear(head);
		return head;
	}
	else if(pos == 0)
	{
		head = link_del_head(head);
		return head;
	}
	else
	{
		Linklist p=head;
		for(int i=0;i<pos-1;i++)
		{
			p=p->next;
		}
		Linklist r=p->next;
		p->next=r->next;
		free(r);
		r=NULL;
		return head;
	}
}
//链表的按照信息删除
Linklist del(Linklist head,int element)
{
	if(head ==NULL)
		return head;
	int pos = find_element(head,element);
	head = link_del_pos(head,pos);
	return head;
}
//链表按照位置删除
int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("请输入服务器IP和端口号!\n");
		return -1;
	}

	int sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1)
	{
		perror("socket 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");
		return -1;
	}
	printf("bind success\n");

	struct sockaddr_in cin;
	cin.sin_family = AF_INET;
	socklen_t socklen = sizeof(cin);

	Linklist Usr_PORT=NULL;
	msg_t usr;
	char buf[149] = "";
	char rbuf[130] = "";
	//根据poll函数IO多路复用
	struct pollfd fds[2];
	fds[0].fd = 0;
	fds[0].events = POLLIN;
	fds[1].fd = sfd;
	fds[1].events = POLLIN;
	int res = 0;  //接收select的返回值

	while(1)
	{
		res = poll(fds,2,-1);
		if(res == -1)
		{
			perror("poll error");
			return -1;
		}
		else if(res == 0)
		{
			printf("time out");
			return -1;
		}
	
		bzero(buf,sizeof(buf));

		if(fds[0].revents == POLLIN)
		{
			strcpy(buf,"SYSMSG:");
			fgets(buf+7,sizeof(buf)-7,stdin);
			buf[strlen(buf)-1] = '\0';
			Linklist p = Usr_PORT;
			while(p!= NULL)
			{
				cin.sin_port = htons(p->PORT);
				sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
				p=p->next;
			}
		}

		if(fds[1].revents == POLLIN)
		{
			
			recvfrom(sfd,&usr,sizeof(usr),0,(struct sockaddr*)&cin,&socklen);
			if(usr.type == 'L')
			{
				Usr_PORT = insert_rear(Usr_PORT,ntohs(cin.sin_port));
			
				printf("[%s:%d]已经上线\n",usr.name,ntohs(cin.sin_port));
				sprintf(buf,"%s已经上线",usr.name);
				printf("buf = %s\n",buf);
				Linklist p = Usr_PORT;
				while(p->next!= NULL)
				{
					cin.sin_port = htons(p->PORT);

					sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
					p=p->next;
				}
			}
			else if(usr.type == 'C')
			{
				sprintf(buf,"%s:%s",usr.name,usr.text);

				Linklist p = Usr_PORT;
				int NONE=ntohs(cin.sin_port);
				while(p!= NULL)
				{
					if(NONE!=p->PORT)
					{
						cin.sin_port = htons(p->PORT);
						sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&(cin),sizeof(cin));
					}
					p=p->next;
				}
			}
			else if(usr.type == 'Q')
			{
				sprintf(buf,"%sdownline",usr.name);
				printf("[%s:%d]downline\n",usr.name,ntohs(cin.sin_port));
				Usr_PORT = del(Usr_PORT,ntohs(cin.sin_port));
				Linklist p = Usr_PORT;
				while(p!= NULL)
				{
					cin.sin_port = htons(p->PORT);
					sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
					p=p->next;
				}
			}
		}
	}
	close(sfd);
	return 0;
}


http://www.niftyadmin.cn/n/5230807.html

相关文章

【ONNX】多个ONNX 模型合并为一个模型

ONNX 模型直接合并&#xff0c;输入和输出不一致也可以&#xff0c;各自输入输出各自的 示例代码 import onnxruntime# version : 1.16.0 import onnxdef log_model(model):model_1_outs {o.name for o in model.graph.output}model_1_ins {i.name for i in model.graph.in…

Lazada详情API接口:一键获取商品信息的深度实践

一、引言 随着电子商务的快速发展&#xff0c;各大电商平台纷纷开放API接口&#xff0c;为开发者提供丰富的数据资源。Lazada作为东南亚地区最大的电商平台之一&#xff0c;同样提供了API接口供开发者使用。本文将详细介绍如何使用Lazada详情API接口一键获取商品信息&#xff…

【matlab程序】画海洋流场

【matlab程序】画海洋流场 clear;clc; file ( ‘0227.nc’); latncread(file,‘latitude’); lonncread(file,‘longitude’); uncread(file,‘water_u’); vncread(file,‘water_v’); [x,y]meshgrid(lon,lat); xx’; yy’; interval4; figure (1) set(gcf,‘color’,[1 1 1…

tensorflow-gpu1.15 + win11 + RTX 4050环境配置

组了一套&#xff0c;不知道行不行 windows11GPURTX 4050python3.7.12tensorflow-gpu1.15.0cudatoolkit10.0.130cudnn7.6.5Keras2.3.1

C#基础与进阶扩展合集-基础篇(持续更新)

目录 本文分两篇&#xff0c;进阶篇点击&#xff1a;C#基础与进阶扩展合集-进阶篇 一、基础篇 Ⅰ 关键字 Ⅱ 特性 Ⅳ 常见异常 Ⅳ 扩展类型 1、BigInteger 2、Half 3、Decimal 4、可空值类型 5、可空引用类型 6、空合并 7、转义字符 8、StringBuilder 9、Format…

项目实战-编写ssm整合配置文件

1、父工程pom.xml <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>…

vue和react使用上的不同

使用表达式 **react使用js表达式** const name 李四 <h1>你好&#xff0c;我叫{name}</h1> **vue 使用表达式** const name 李四 <div>你好&#xff0c;我叫{{name}}</div>列表渲染 列表渲染 const songs [{ id: 1, name: 痴心绝对 },{ id: 2, n…

如何解决SSL证书部署后未生效或网站显示不安全

本文介绍SSL证书部署后未生效或网站显示不安全的排查方法。 浏览器提示“您与此网站建立的连接不安全” 浏览器提示“无法访问此页面” 浏览器提示“这可能是因为站点使用过期或者不全的TLS安全设置” 浏览器提示“此页面上部分内容不安全&#xff08;例如图像&#xff09;”…