2024.3.7

1、基于UDP的网络聊天室

服务器:

#include<myhead.h>//定义一个结构体存储成员信息
typedef struct Node
{struct sockaddr_in cin;struct Node *next;
}*Linklist;//定义一个结构体表示消息类型
typedef struct _msg
{char code;    //L:登录,C:群聊,Q:退出,S:系统消息char name[20];char text[128];
}msg_t;
//登录操作的函数
int do_login(int sfd,msg_t msg,Linklist head,struct sockaddr_in cin)
{//打印登录成功printf("%s [%s:%d]登录成功\n,",msg.name, (char*)inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));sprintf(msg.text,"----------%s登陆成功---------\n",msg.name);//先遍历链表,将新用户加入群聊的消息发给所有人Linklist p = head;while(p->next != NULL){p = p->next;//给客户端发送消息sendto(sfd, &msg, sizeof(msg), 0, (struct sockaddr*)&(p->cin), sizeof(p->cin));}//将新用户的网络信息结构体,头插入链表Linklist temp = NULL;if((temp = (Linklist)malloc(sizeof(struct Node*))) == NULL){printf("malloc error\n");return -1;}temp->cin = cin;temp->next = NULL;head->next = temp;return 0;
}
void do_chat(int sfd, msg_t msg, Linklist head,struct sockaddr_in cin)
{printf("%s [%s:%d]chat成功\n",msg.name,(char*)inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));char buf[200]="";sprintf(buf, "%s:%s",msg.name, msg.text);strcpy(msg.text, buf);//遍历链表,将群聊消息发送给客户端Linklist p = head;while(p->next != NULL){p = p->next;//判断是否给自己发送消息if(memcmp(&cin, &(p->cin), sizeof(cin))){sendto(sfd, &msg, sizeof(msg), 0, (struct sockaddr*)&(p->cin), sizeof(p->cin));}}return ;
}
void do_quit(int sfd,msg_t msg,Linklist head, struct sockaddr_in cin)
{sprintf(msg.text,"---------%s已下线------\n",msg.name);//遍历链表,是自己就将自己在链表里删除//不是自己就发送下线通知Linklist p=head;Linklist del = NULL;while(p->next != NULL){if(memcmp(&(p->next->cin),&cin,sizeof(cin))){//不是自己sendto(sfd,&msg,sizeof(msg), 0, (struct sockaddr*)&(p->cin),sizeof(p->cin));}else{del = p->next;p->next = del->next;free(del);del = NULL;}}return ;
}
int main(int argc, const char *argv[])
{//判断终端输入是否违规if(argc != 3){printf("请输入ip地址和端口号!!!\n");return -1;}//1、创建用于通信的套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd == -1){perror("socket error");return -1;}//2、绑定//填充地址信息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]);   //ip地址//将地址信息绑定到服务器if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("bind error\n");return -1;}//定义客户端地址信息用于接收struct sockaddr_in cin;socklen_t socklen = sizeof(cin);msg_t msg;      //定义接收的消息pid_t pid = fork();if(pid == -1){perror("fork error");return -1;}else if(pid > 0){//父进程:用于发送系统消息strcpy(msg.name, "*ststem*:");msg.code = 'C';   //服务端向客户端群发消息while(1){//清空消息结构体memset(&msg,0,sizeof(msg));//输入要发送的消息fgets(msg.text, sizeof(msg.text), stdin);msg.text[strlen(msg.text)-1] = 0;//发送消息sendto(sfd, &msg, sizeof(msg), 0, (struct sockaddr*)&sin, sizeof(sin));}}else{//子进程//创建链表头结点存储客户端信息Linklist head=NULL;head = (Linklist)malloc(sizeof(struct Node));if(head == NULL){printf("error\n");return -1;}memset(head, 0, sizeof(head));head->next = NULL;while(1){//清空数据和新用户信息memset(&msg, 0, sizeof(msg));memset(&cin, 0, sizeof(cin));//接收客户端发送的信息recvfrom(sfd, &msg, sizeof(msg), 0, (struct sockaddr*)&cin, &socklen);//判断消息操作码switch(msg.code){case 'L':{do_login(sfd, msg, head, cin);}break;case 'C':{do_chat(sfd, msg, head, cin);}break;case 'Q':{do_quit(sfd, msg, head, cin);}break;}}}return 0;
}

客户端:

#include<myhead.h>//定义消息类型结构体
typedef struct msg
{char code; //操作码char name[20];char text[128];
}msg_t;
typedef void (*sighandler_t)(int);
void handler(int sig)
{//回收子进程资源并退出while(waitpid(-1, NULL, WNOHANG) > 0);exit(0);
}int main(int argc, const char *argv[])
{//判断终端输入if(argc != 3){printf("请输入ip地址和端口号!\n");return -1;}//注册信号处理函数,让子进程退出后,父进程回收子进程资源并退出sighandler_t s = signal(SIGCHLD, handler);if(s == SIG_ERR){perror("signal error");return -1;}//创建用于通信的套接字int cfd = socket(AF_INET, SOCK_DGRAM, 0);if(cfd == -1){perror("socket error");return -1;}//2、绑定//填充地址信息结构体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]);//清空消息内容msg_t msg;memset(&msg, 0, sizeof(msg));//输入用户名printf("请输入用户名>>>");fgets(msg.name, sizeof(msg.name), stdin);msg.name[strlen(msg.name)-1] = 0;msg.code = 'L';//给服务器发送消息sendto(cfd, &msg,sizeof(msg),0, (struct sockaddr*)&sin,sizeof(sin));//创建进程pid_t pid = fork();if(pid == -1){perror("fork error");return -1;}else if(pid > 0){//父进程//循环终端接受数据并发给客户端while(1){memset(msg.text, 0, sizeof(msg.text));fgets(msg.text, sizeof(msg.text),stdin);    //在终端获取聊天信息msg.text[strlen(msg.text)-1] = 0;//判断输入的聊天内容if(strcmp(msg.text,"quit") == 0){msg.code = 'Q';strcpy(msg.text, "下线了");}else{msg.code = 'C';}sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));if(msg.code == 'Q')exit(0);}}else{//子进程//循环接收并打印消息while(1){recvfrom(cfd, &msg, sizeof(msg), 0, NULL,NULL);}printf("[%s]:%s\n",msg.name,msg.text);}close(cfd);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3+element plus 实现百度地图显示路径

添加依赖 <!-- index.html --><script type"text/javascript" src"//api.map.baidu.com/getscript?v3.0&akyI6kBeC9G4LntEWXklE2iNHwRUrmFEQc"></script><script type"text/javascript" src"//api.map.baidu.co…

利用Python爬取高德地图全国地铁站点信息

利用Python中的requests库进行地铁站点信息的获取,同时将数据保存在本机excel中 # 首先引入所需要的包 import requests from bs4 import BeautifulSoup import pandas as pd import json# 发送 GET 请求获取网页内容 url http://map.amap.com/subway/index.html response r…

【算法沉淀】刷题笔记:并查集 带权并查集+实战讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

ospf虚链路实验简述

1、ospf虚链路实验简述 ospf虚链路配置 为解决普通区域不在骨干区域旁&#xff0c;通过配置Vlink-peer实现不同区域网络设备之间建立逻辑上的连接。 实验拓扑图 r1: sys sysname r1 undo info enable int loopb 0 ip add 1.1.1.1 32 ip add 200.200.200.200 32 quit int e0/0/…

模拟实现std::string类(包含完整、分文件程序)

std库中的string是一个类&#xff0c;对string的模拟实现&#xff0c;既可以复习类的特性&#xff0c;也可以加深对std::string的理解。 &#x1f308;一、搭建框架 ☀️1.新命名空间 本质上string是一个储存在库std里面的类&#xff0c;现在需要模拟实现一个string类&#…

python基础——入门必备知识

&#x1f4dd;前言&#xff1a; 本文为专栏python入门基础的第一篇&#xff0c;主要带大家先初步学习一下python中的一些基本知识&#xff0c;认识&#xff0c;了解一下python中的一些专有名词&#xff0c;为日后的学习打下良好的基础,。本文主要讲解以下的python中的基本语法&…

力扣706:设计哈希映射

题目&#xff1a; 不使用任何内建的哈希表库设计一个哈希映射&#xff08;HashMap&#xff09;。 实现 MyHashMap 类&#xff1a; MyHashMap() 用空映射初始化对象void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中&#x…

tcpdump使用pcap-filter抓Vxlan包内数据

目录 1. 背景2. 参考3. 概念4. 环境5. 用法5.1 抓vxlan通讯中的icmp包5.2 tcpdump抓包命令解析5.2.1 tcpdump命令说明5.2.2 Vxlan协议报文解析 5.3 其他抓包例子5.3.1 抓包示例15.3.2 抓包示例2 1. 背景 看vxlan协议时&#xff0c;发现可以使用tcpdump高级用法&#xff08;pca…

Unity Samples和帧动画的问题

拖动序列帧图片和自己创建clip的帧率不同 我今天在创建帧动画的时候用了两种方式第一种是直接拖动序列帧图片到Hierachy&#xff0c;然后生成的第二种是这样我发现两者播放的动画速率不一样最后查了半天查不到原因。最后发现是Samples的原因&#xff0c;而且Unity把Samples这个…

智能控制:物联网智能插座对接文档

介绍 一开始买的某米的插座&#xff0c;但是好像接口不开放&#xff0c;所以找到了这个插座&#xff0c;然后自己开发了下&#xff0c;用接口控制插座开关。wifi的连接方式&#xff0c;通电后一般几秒后就会连接上wifi&#xff0c;这个时候通过接口发送命令给他。 产品图片 通…

b站小土堆pytorch学习记录—— P25-P26 网络模型的使用和修改、保存和读取

文章目录 一、修改1.方法2.代码 二、保存和读取1.方法2.代码&#xff08;1&#xff09;保存&#xff08;2&#xff09;加载 3.陷阱 一、修改 1.方法 add_module(name: str, module: Module) -> None name 是要添加的子模块的名称。 module 是要添加的子模块。 调用 add_m…

Android车载开发之AAOS快速入门

一、概述 在正式介绍Android Automotive OS之前,我们先弄清两个概念:Android Auto和Android Automotive OS。 Android Auto Android Auto 不是操作系统,而是一个应用或一个服务。当 Android 手机通过无线或有线方式连接到汽车时,Android 系统会将使用 Android Auto 服务…

python爬虫(一)

一、python中的NumPy模块&#xff08;数据的存储和处理&#xff09; 这里是下载完成之后的表现 &#xff08;1&#xff09;创建数组 1、使用array&#xff08;&#xff09;函数创建数组 使用array函数可以创建任意维度的的数组 下面是一个创建二维数组的代码示例 下面是代码…

每日五道java面试题之springMVC篇(一)

目录&#xff1a; 第一题. 什么是Spring MVC&#xff1f;简单介绍下你对Spring MVC的理解&#xff1f;第二题. Spring MVC的优点第三题. Spring MVC的主要组件&#xff1f;第四题. 什么是DispatcherServlet?第五题. 什么是Spring MVC框架的控制器&#xff1f; 第一题. 什么是S…

unity学习(49)——服务器三次注册限制以及数据库化角色信息4--角色信息数据库化

1.此处下断开始调试,list函数内就有问题&#xff1a; 2. 现在的问题是只读不写&#xff01;32行就是写入部分的代码&#xff1a; 3. 很奇怪&#xff0c;调试的时候确实是写进来了 程序正常执行后&#xff0c;文件中数据也没有消失 关闭服务器文件内容依旧正常。 players包含所…

安装sqlserver2022最新版只能使用.\SQLEXPRESS登录数据库怎么修改成.

.\SQLEXPRESS “服务器名称 localhost\SQLEXPRESS”中的 “SQLEXPRESS”就是数据库的实例名称/数据库名/服务器名&#xff0c; “localhost”即登录本计算机安装的数据库 安装sqlserver2022最新版只能使用.\SQLEXPRESS登录数据库怎么修改成. 2、查看SQL Server数据库的实例名…

Python从0到100(二):Python语言介绍及第一个Pyhon程序

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

导数与微分错题本

《1800》 1 缺乏构造函数的技巧 2 3 等价无穷小+构造函数 4

请说明Vue中的Error Boundaries

当我们开发基于Vue框架的应用时&#xff0c;我们经常会遇到各种错误处理的情况。Vue提供了一种非常强大且简单的方式来处理这些错误&#xff0c;那就是Error Boundaries&#xff08;错误边界&#xff09;。本文将从概念、用法和示例代码三个方面来详细介绍Vue中的Error Boundar…

SSD LDPC软错误探测方案解读

上一篇文档中,基于SSD LDPC(Low-Density Parity-Check Codes)原理背景和纠错能力作了简单的介绍。 扩展阅读: 关于SSD LDPC纠错能力的基础探究 浅析LDPC软解码对SSD延迟的影响 本篇结合SMI发布的研究成果,通过SSD控制内部LDPC更底层的架构,来解读如何增强软错误探测能力…