基于UDP网络聊天室OICQ
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;
}
相关文章:
基于UDP网络聊天室OICQ
Linux系统 Gcc Gdb makefile 实现局域网OICQ程序设计,包括客户端和服务端。 客户端描述:客户端运行开始出现登陆界面。与服务端进行连接,连接后把账号信息发送给服务端,服务端验证后,把确认结果通知客户端。如果通…...

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用
基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介绍…...
【微信小程序】保存多张图片到本地相册 wx.saveImageToPhotosAlbum
这里写目录标题 微信小程序检测是否有存储权限wx.getSetting 图片上传从HTML中提取img标签的src属性多图片下载 微信小程序检测是否有存储权限 wx.getSetting 上传前判断是否开启存储权限,如果不检测直接上传会出现fail的情况 var _this this wx.getSetting({su…...

【Android】使用intent.putExtra()方法在启动Activity时传递数据
食用方法 在Android中,你可以使用Intent对象来在启动Activity时传递数据。以下是一个示例,展示了如何在startActivity时传递数据到被启动的Activity: 在启动Activity的地方,创建一个Intent对象,并使用putExtra()方法…...

数据结构与算法编程题35
用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct B…...
每日一题 - 231201 - Divisibility by Eight
Divisibility by Eight TAG - 整除特性、枚举 整除特性、枚举 整除特性、枚举时间复杂度 - O ( N 3 ) O(N^3) O(N3) // #include<bits/stdc.h> using namespace std; // #define int long long void solve() {string s;cin>>s;for( int i0;i<s.size();i )if(…...

虚幻学习笔记1—给UI添加动画
一、前言 本文所使用的虚幻版本为5.3.2,之前工作都是用unity,做这类效果用的最多的是一个DoTween的插件,在虚幻中都内置集成了这这种效果制作。 图1.1 UI动画 二、过程 1、首先,在诸如按钮、图像等可交互控件中选中,如…...

【RabbitMQ】RabbitMQ快速入门 通俗易懂 初学者入门
目录 1.初识MQ 1.1.同步和异步通讯 1.1.1.同步通讯 1.1.2.异步通讯 1.2.技术对比: 2.快速入门 2.1.安装RabbitMQ 2.2.RabbitMQ消息模型 2.3.导入Demo工程 2.4.入门案例 2.4.1.publisher实现 2.4.2.consumer实现 2.5.总结 3.SpringAMQP 3.1.Basic Que…...

JAVEE初阶 多线程基础(四)
线程安全 一.线程安全存在的问题二.锁三.关于锁的理解四.关于锁操作混淆的理解4.1两个线程是否对同一对象加锁 一.线程安全存在的问题 为什么这里的count不是一百万呢?这就是线程所存在的不安全的问题,由于线程是抢占式执行,同时执行count,操作本质是三个指令 1.load 读取内存…...
【C 语言经典100例】C 练习实例19
题目:一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如61+2+3.编程找出1000以内的所有完数。 程序分析:请参照:C 练习实例14。 #include<stdio.h> #define N 1000 int main() {…...

Jmeter+Maven+jenkins+eclipse搭建自动化测试平台
背景: 首先用jmeter录制或者书写性能测试的脚本,用maven添加相关依赖,把性能测试的代码提交到github,在jenkins配置git下载性能测试的代码,配置运行脚本和测试报告,配置运行失败自动发邮件通知,…...

springboot+jsp+java人才招聘网站4f21r
本基于springboot的人才招聘网站主要满足3种类型用户的需求,这3种类型用户分别为求职者、企业和管理员,他们分别实现的功能如下。 (1)求职者进入网站后可查看职位信息、企业信息以及职位新闻等,注册登录后可实现申请职…...

WordPress:构建强大的网站和博客的完美选择
WordPress:构建强大的网站和博客的完美选择 一、WordPress 简介1.1 WordPress 介绍1.2 WordPress 优势 二、部署LNMP环境2.1 前提条件2.2 关闭防火墙和SELinux2.3 安装Nginx2.4 安装MySQL2.5 安装PHP2.6 配置Nginx2.7 配置MySQL2.8 配置PHP2.9 测试访问LNMP平台 三、…...

2021年8月18日 Go生态洞察:整合Go的网络体验
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

【算法】缓存淘汰算法
目录 1.概述2.代码实现2.1.FIFO2.2.LRU2.3.LFU2.4.Clock2.5.Random 3.应用 1.概述 缓存淘汰策略是指在缓存容量有限的情况下,当缓存空间不足时决定哪些缓存项应当被移除的策略。缓存淘汰策略的目标是尽可能地保持缓存命中率高,同时合理地利用有限的缓存…...
接手项目要做的事项
总结:在接手别人的项目时,至少应该自己整理并绘画四个图 1、产品脑图:帮助你理解产品的功能; 2、UML时序图:帮助你源代码的核心技术实现; 3、整体业务泳道图:帮助你从整体上熟悉业务的流程&a…...

【Web】攻防世界Web_php_wrong_nginx_config
这题考察了绕过登录、目录浏览、后门利用 进来先是一个登录框,随便怎么输前端都直接弹窗 禁用js后再输入后登录 查看源码,好家伙,不管输什么都进不去 直接扫目录 访问/robots.txt 访问/hint.php 访问/Hack.php 抓包看一下 cookie里isLogin0…...
Flume采集Kafka并把数据sink到OSS
安装环境 Java环境, 略 (Flume依赖Java)Flume下载, 略Scala环境, 略 (Kafka依赖Scala)Kafak下载, 略Hadoop下载, 略 (不需要启动, 写OSS依赖) 配置Hadoop 下载JindoSDK(连接OSS依赖), 下载地址Github 解压后配置环境变量 export JINDOSDK_HOME/usr/lib/jindosdk-x.x.x expo…...

flutter,uni-app开发调试ios
一、申请ios开发者账号 二、ios开发者配置 ios 开发者需要配置的地方 https://developer.apple.com/account/resources/certificates/list Certificates(证书): 作用: 证书用于对应用程序和开发者进行身份验证,确保安全性和可…...
MybatisBatchUtils功能介绍
MybatisBatchUtils 是一个 MyBatis 框架的工具类,主要用于简化 MyBatis 中批量操作的代码编写。该工具类封装了 MyBatis 中的批量操作方法,可以方便地进行批量插入、更新和删除等操作。 一般来说,使用 MyBatis 进行批量操作需要先设置 JDBC 驱…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...