2024.1.19 网络编程 作业

思维导图

练习题

1> UDP传输实现聊天室

服务器端

#include <myhead.h>
#define SER_IP "192.168.125.151"
#define SER_PORT 9999
typedef struct Msg
{
    char user[32];   //用户名
    int type;        //执行操作1.登录、2.发消息、0.退出
    char text[1024]; //消息内容
} msg_t;
typedef struct List
{
    struct sockaddr_in cin; //客户端的网络信息结构体
    struct List *next;      //链表指针,指向下一个
} * list;

struct sockaddr_in cin;
//创建头节点
list list_create()
{
    list p = (list)malloc(sizeof(struct List));
    if (p == NULL)
    {
        perror("create list error");
    }
    p->next = NULL;
    p = NULL;
}
//线程函数事件 向所有客户端发送消息
void *task(void *arg)
{
    int *sockfd = (int *)arg;
    msg_t msg;
    strcpy(msg.user, "*system*");
    while (1)
    {
        scanf("%s", msg.text);
        getchar();
        if (strncmp(msg.text, "quit", 4) == 0)
        {
            exit(0);
        }
        sendto(*sockfd, msg.text, sizeof(msg), 0, (struct sockaddr *)&cin, sizeof(cin));
    }
}
//登录事件处理
void login(int sockfd, msg_t msg, list p, struct sockaddr_in cin)
{
    //新客户端插入链表
    list new = NULL;
    new = (list)malloc(sizeof(struct List));
    sprintf(msg.text, "login");
    while (p->next != NULL)
    {
        //发送给的其他客户端登录消息
        p = p->next;
        sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
        printf("[%s:%d]:%s login\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.user);
    }
    //新节点的数据域填充新客户端地址结构体,尾插
    new->cin = cin;
    p->next = new;
    new->next = NULL;
}
//接收客户端消息事件处理
void chatmsg(int sockfd, msg_t msg, list p, struct sockaddr_in cin)
{
    //将客户端发来的消息发送给其他客户端
    while (p->next != NULL)
    {
        p = p->next;
        sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
    }
}
//客户端退出消息事件处理
void quit(int sockfd, msg_t msg, list p, struct sockaddr_in cin)
{
    list del = NULL;
    sprintf(msg.text, "%s out", msg.user);
    while (p->next != NULL)
    {
        //遍历链表找到要退出的客户端地址结构体的前一个
        if (memcmp(&(p->next->cin), &cin, sizeof(cin)) == 0)
        {
            del = p->next;
            p->next = del->next;
            free(del);
            del = NULL;
        }
        else
        {
            p = p->next;
            sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
        }
    }
}
int main(int argc, char const *argv[])
{
    msg_t msg;
    //创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket error");
        return -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);
    //绑定服务器
    if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    //创建客户端地址结构体
    struct sockaddr_in cin;
    //获取客户端地址结构体大小
    socklen_t socklen = sizeof(cin);
    //创建链表节点
    list p = list_create();
    //创建线程
    pthread_t tid;
    if (pthread_create(&tid, NULL, task, &sockfd) == -1)
    {
        printf("pthread_create error\n");
        return -1;
    }
    //分离线程
    pthread_detach(tid);
    //接收客户端消息
    while (1)
    {

        //接收客户端发来的消息,返回消息字符个数
        int res = recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &socklen);
        if (res < 0)
        {
            perror("recvfrom error");
            return -1;
        }
        //判断三种客户端状态 1登录 2消息 0退出
        if (msg.type == 1)
        {
            login(sockfd, msg, p, cin);
        }
        else if (msg.type == 2)
        {
            chatmsg(sockfd, msg, p, cin);
        }
        else if (msg.type == 0)
        {
            printf("[%s:%d] %s out\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.user);
            quit(sockfd, msg, p, cin);
        }
    }
    //关闭套接字
    close(sockfd);
    return 0;
}

客户端

#include <myhead.h>
#define SER_IP "192.168.125.151"
#define SER_PORT 9999
typedef struct Msg
{
    char user[32];   //用户名
    int type;        //执行操作1.登录、2.发消息、0.退出
    char text[1024]; //消息内容
} msg_t;
int main(int argc, char const *argv[])
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("sock error");
        return -1;
    }
    msg_t msg;
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_addr.s_addr = inet_addr(SER_IP);
    cin.sin_port = htons(SER_PORT);
    socklen_t socklen = sizeof(cin);
    char buf[128] = "";

    msg.type = 1;
    printf("please imput your name:");
    scanf("%s", msg.user);
    getchar();

    sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, socklen);

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork error");
        return -1;
    }
    else if (pid == 0) //子进程循环发送消息
    {
        while (1)
        {
            printf("---------------------\n");
            scanf("%s", msg.text);
            getchar();
            if (strncmp(msg.text, "quit", 4) == 0)
            {
                msg.type = 0;
                sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, socklen);
                kill(pid, SIGINT);
                exit(0);
                wait(NULL);
            }
            else
            {
                msg.type = 2;
            }
            sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, socklen);
        }
    }
    else //父进程循环接受消息
    {
        int res;
        while (1)
        {
            res = recv(sockfd, &msg, sizeof(msg), 0);
            if (res == -1)
            {
                perror("recv error");
                return -1;
            }
            printf("[%s]:%s\n", msg.user, msg.text);
        }
        wait(NULL);
    }
    close(sockfd);
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NOC总线(1)

1. 背景 SoC &#xff08;system on chip,片上系统&#xff09;通常指在单一芯片上实现的数字计算机系统&#xff0c;总线结构是该系统的主要特征&#xff0c;由于其可以提供高性能的互连而被广泛运用。随着单芯片上集成的处理器核数越来越多&#xff0c;片上互连架构经历了从专…

sqlmap使用教程(2)-连接目标

目录 连接目标 1.1 设置认证信息 1.2 配置代理 1.3 Tor匿名网络 1.4 检测WAF/IPS 1.5 调整连接选项 1.6 处理连接错误 连接目标 场景1&#xff1a;通过代理网络上网&#xff0c;需要进行相应配置才可以成功访问目标主机 场景2&#xff1a;目标网站需要进行身份认证后才…

【git分支管理策略】

文章目录 前言一、分支管理策略简介二、git基本操作三、git分支远程分支本地分支 四、gitflow分支管理策略分支定义gitflow分支管理策略评价 五、GITHUB FLOW分支管理策略分支使用流程创建分支&#xff08;Create a branch&#xff09;新增提交(add and commit)提出 Pull 请求&…

关联系统-智能座舱控制器ICC

智能座舱构成 如上图所示&#xff0c;智能座舱主要是由仪表、中控、HUD、语音、DMS/OMS等多种交互通道组成&#xff0c;其宗旨是提升人的交互体验&#xff0c;使车辆更加智能化&#xff0c;情感化。 智能座舱内部功能 仪表功能 SR场景重构 如上图所示&#xff0c;仪表区域可实…

k8s的包管理工具helm

Helm是什么? 之前的这篇文章介绍了一开始接触k8s的时候接触到的几个命令工具 kubectl&kubelet&rancher&helm&kubeadm这几个命令行工具是什么关系&#xff1f;-CSDN博客 Helm 是一个用于管理和部署 Kubernetes 应用程序的包管理工具。它允许用户定义、安装和…

Linux软件包管理器yum

文章目录 前言概述Linux下载软件的三种方式源代码安装rpm安装yum安装 关于yum的相关操作查看软件包软件安装卸载软件 yum源问题 前言 在Windows系统中&#xff0c;如果我们要去下载软件&#xff0c;我们可以在该软件的官网中进行下载&#xff0c;或者在微软的额软件商店进行下…

设计亚马逊按销售排名功能

1&#xff1a; 定义 Use Cases 和 约束 Use cases 作用域内的Use Case Service 通过目录计算过去一周内最受欢迎的产品User 通过目录去View过去周内最受欢迎的产品Service 有高可用 作用域外 整个电商网站 设计组件&#xff08;只是计算销售排名&#xff09; 约束和假设…

经典面试题-死锁

目录 1.什么是死锁&#xff1f; 2.形成死锁的四个必要条件 3.死锁的三种情况 第一种情况&#xff1a; 举例&#xff1a; 举例&#xff1a; 第二种情况&#xff1a;两个线程 两把锁 举例&#xff1a; 第三种情况&#xff1a;N个线程 M把锁 哲学家进餐问题 1.什么是死锁&…

java黑马学习笔记

数组 变量存在栈中&#xff0c;变量值存放在堆中。 数组反转 public class test{public static void main(String[] args){//目标&#xff1a;完成数组反转int[] arr {10,20,30,40,50};for (int i 0,j arr.length - 1;i < j;i,j--){int tep arr[j]; //后一个值赋给临时…

【Linux】解决普通用户无法进行sudo提权

当某个普通用户进行sudo指令提权的时候&#xff0c;可能存在无法操作的问题&#xff0c;如下图&#xff1a; 这个图中有一个细节&#xff0c;我们使用sudo进行提权的时候&#xff0c;用的可是zhangsan的密码&#xff0c;因此有人可能会有疑问&#xff0c;这不是有问题吗&#x…

爬虫-selenium自动化(3)-验证码

#验证码分很多种&#xff0c;奇葩也无处不在:哪个是真茅台&#xff0c;红绿灯&#xff0c;摩托车......(我是个人都看不出来) (๑﹏๑) #本节内容为selenium自动化实现验证码通过-------字符验证码&#xff0c;点触验证码。 验证码介绍 字符验证码案例 点触验证码案例

如何在WordPress网站中添加多语言搜索(2种简单方法)

您想在WordPress网站中添加多语言搜索吗&#xff1f; 如果您有一个多语言 WordPress 网站&#xff0c;那么添加多语言搜索功能可以帮助用户通过使用自己的语言进行搜索来更快地找到信息。 在本文中&#xff0c;我们将向您展示如何在 WordPress 中轻松添加多语言搜索&#xff…

Springboot常见报错及解决方案

1、多模块项目无法启动&#xff0c;报错Failed to execute goal on project*: Could not resolve dependencies for project 2、报错找不到符号&#xff08;在多moudle调用的时候&#xff0c;公共模块新增了东西的时候发生&#xff09; Rebuild项目 3、切换分支一开始跑不了的…

PowerShell install 一键部署grafana

grafana 前言 Grafana 是一款开源的数据可视化和监控仪表盘工具。它提供了丰富的数据查询、可视化和报警功能,可用于实时监控、数据分析和故障排除等领域。 通过 Grafana,您可以连接到各种不同的数据源,包括时序数据库(如 Prometheus、InfluxDB)和关系型数据库(如 MySQ…

解决ssh登录Permission denied, please try again

现象截图如下&#xff1a; 确定root的密码是正确的&#xff0c;最后的原因找到了&#xff0c;是远程的服务器&#xff0c;禁用了root账户可以被远程访问的权限。开启操作如下&#xff1a; 1.编辑配置文件 vi /etc/ssh/sshd_config 2.文件中找到PermitRootLogin #PermitRoo…

静态路由实验

一&#xff1a;实验内容 二&#xff1a;实验分析 &#xff08;一&#xff09;&#xff1a;实验要求 1、R6为ISP&#xff0c;接口IP地址均为公有地址&#xff1b;该设备只能配置IP地址&#xff0c;之后不能再对其进行其他任何配置&#xff1b; 2、R1-R5为局域网&#xff0c…

鸿蒙开发(七)添加常用控件(上)

相信大家已经对鸿蒙开发的布局有了基本的了解。之前我们提到过&#xff0c;一个好的UI&#xff0c;离不开选择合理的布局。当然&#xff0c;也离不开适当的控件。本篇文章&#xff0c;带着大家一起学习下如何在页面里面添加常用的控件。由于控件较多&#xff0c;我会分为两篇文…

HarmonyOS SDK,助力开发者打造焕然一新的鸿蒙原生应用

鸿蒙生态千帆启航仪式于1月18日正式启动。从2019年HarmonyOS正式发布到2020年“没有人能够熄灭漫天星光”&#xff0c;今天&#xff0c;满天星光终汇成璀璨星河&#xff0c;HarmonyOS NEXT鸿蒙星河版重磅发布&#xff0c;带来了全新架构、全新体验、全新生态。作为支撑鸿蒙原生…

设计模式——1_5 享元(Flyweight)

今人不见古时月&#xff0c;今月曾经照古人 ——李白 文章目录 定义图纸一个例子&#xff1a;可以复用的样式表绘制表格降本增效&#xff1f;第一步&#xff0c;先分析 变化和不变的地方第二步&#xff0c;把变化和不变的地方拆开来第三步&#xff1a;有没有办法共享这些内容完…

C++(Qt)软件调试---静态分析工具clang-tidy(18)

C(Qt)软件调试—静态分析工具clang-tidy&#xff08;18&#xff09; 文章目录 C(Qt)软件调试---静态分析工具clang-tidy&#xff08;18&#xff09;1、概述2、clang-tidy基本用法3、目前已有检查项4、Qt Creator中安装clang-tidy5、Qt Creator中使用clang-tidy6、Clang-Tidy配置…