2024.8.19 学习记录 —— 作业

news2024/12/28 18:54:32

一、TCP机械臂测试

#include <myhead.h>

#define SER_PORT 8888          // 与服务器保持一致
#define SER_IP "192.168.0.114" // 服务器ip地址

int main(int argc, const char *argv[])
{
    // 创建文件描述符打开键盘文件
    int fd = open("/dev/input/event1", O_RDONLY);
    if (fd == -1)
    {
        perror("open error");
        return -1;
    }

    // 定义结构体接收键盘文件的数据
    struct input_event ie;

    // 创建用于通信的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("cfd = %d\n", cfd); 

    // 连接到服务器
    // 填充服务器地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;                // 通信域
    sin.sin_port = htons(SER_PORT);          // 服务器端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP); // 服务器ip地址

    // 连接服务器
    if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("connect error");
        return -1;
    }
    printf("连接服务器成功\n");

    // 准备数据
    char rbuf[5] = {0xff, 0x02, 0x00, 0x10, 0xff};
    unsigned char bbuf[5] = {0xff, 0x02, 0x01, 0x10, 0xff};

    // 发送给服务器,以初始化机械臂
    send(cfd, rbuf, sizeof(rbuf), 0);
    sleep(1);
    send(cfd, bbuf, sizeof(bbuf), 0);
    printf("%#x\n", rbuf[3]);
    printf("%#x\n", bbuf[3]);

    while (1)
    {
        // 接收键盘文件数据
        read(fd, &ie, sizeof(ie));
        switch (ie.code * ie.value)
        {
        case 32: // d键
            rbuf[3] += 1;
            if (rbuf[3] > 90)
            {
                rbuf[3] = 90;
            }
            send(cfd, rbuf, sizeof(rbuf), 0); // 传输数据给机械臂
            break;
        case 30: // a键
            rbuf[3] -= 1;
            if (rbuf[3] < -90)
            {
                rbuf[3] = -90;
            }
            send(cfd, rbuf, sizeof(rbuf), 0); // 传输数据给机械臂
            break;
        case 31: // s键
            bbuf[3] -= 1;
            if (bbuf[3] <= 0)
            {
                bbuf[3] = 0;
            }
            send(cfd, bbuf, sizeof(bbuf), 0); // 传输数据给机械臂
            break;
        case 17: // w键
            bbuf[3] += 1;
            if (bbuf[3] > 180)
            {
                bbuf[3] = 180;
            }
            if (bbuf[3] < 0)
            {
                bbuf[3] = 0;
            }
            send(cfd, bbuf, sizeof(bbuf), 0); // 传输数据给机械臂
            break;

        default:
            break;
        }
        /*
        if (buf == 'd') // 红机械臂右移一度
        {
            rbuf[3] = rbuf[3] + 1; // 修改角度
            printf("%#x\n", rbuf[3]);
            send(cfd, rbuf, sizeof(rbuf), 0); // 传输结果
        }
        if (buf == 'a') // 红机械臂左移一度
        {
            rbuf[3] = rbuf[3] - 1;
            printf("%#x\n", rbuf[3]);
            send(cfd, rbuf, sizeof(rbuf), 0);
        }
        if (buf == 's') // 蓝机械臂上移一度
        {
            bbuf[3] = bbuf[3] + 1;
            printf("%#x\n", bbuf[3]);
            send(cfd, bbuf, sizeof(bbuf), 0);
        }
        if (buf == 'w') // 蓝机械臂下移一度
        {
            bbuf[3] = bbuf[3] - 1;
            printf("%#x\n", bbuf[3]);
            send(cfd, bbuf, sizeof(bbuf), 0);
        }
        if (buf == 'q') // 直接设置
        {
            int val = 0;
            printf("红机械臂增减角度:");
            scanf("%d", &val);        // 获取增减角度
            rbuf[3] = rbuf[3] + val;  // 修改角度
            printf("%#x\n", rbuf[3]); // 传输结果
            getchar();

            printf("蓝机械臂增减角度:");
            scanf("%d", &val);
            bbuf[3] = bbuf[3] + val;
            printf("%#x\n", bbuf[3]);
            getchar();

            send(cfd, rbuf, sizeof(rbuf), 0);
            usleep(100);
            send(cfd, bbuf, sizeof(bbuf), 0);
        }
        buf = 0;
        */
    }

    // 5、关闭套接字
    close(cfd);

    return 0;
}

二、基于UDP的TFTP文件传输

#include <myhead.h>
int main(int argc, char const *argv[])
{
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sfd == -1)
    {
        perror("socket error");
        return -1;
    }

    // 下载请求包
    char buf[516] = "";

    short *p1 = (short *)buf; // 操作码
    *p1 = htons(1);

    char *p2 = buf + 2; // 文件名
    strcpy(p2, "5.png");

    char *p4 = p2 + strlen(p2) + 1; // 模式位
    strcpy(p4, "octet");

    int size = 2 + strlen(p2) + strlen(p4) + 2; // 请求包总长

    // 服务器地址信息
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(69);
    sin.sin_addr.s_addr = inet_addr("192.168.0.114");

    // 向服务器发送a下载请求
    sendto(sfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));

    int newfd = 0;
    if ((newfd = open("./5.png", O_WRONLY | O_CREAT | O_APPEND | O_TRUNC, 0664)) == -1)
    {
        perror("open error");
        return -1;
    }

    while (1)
    {
        socklen_t size_sin = sizeof(sin);
        bzero(buf, sizeof(buf)); // 清空buf

        int res = 0; // 接收服务器发送的数据
        if ((res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, &size_sin)) == -1)
        {
            perror("recvform error");
            return -1;
        }
        
        if (res <516)
        {
            write(newfd, buf + 4, res - 4);
            *p1 = htons(4);
            sendto(sfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin));
            printf("下载结束\n");
            break;
        }
        
        write(newfd, buf + 4, res - 4);                               // 写入数据
        *p1 = htons(4);                                               // 操作码置位 4
        sendto(sfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin)); // 发送ACK
    }

    close(sfd);
    close(newfd);
    return 0;
}

 三、基于UDP的聊天室

1、服务器端

#include <myhead.h>
#define SER_PORT 6666            // 服务器端口号
#define SER_IP "192.168.179.128" // 服务器ip地址
// 定义结构体用于存储客服端的信息
struct MSG
{
    char type; // 信息类型 'L'表示登录 'T'表示群聊 'Q'表示退出 'S'表示系统消息

    char name[20];
    char msg[256];
};

// 定义链表用于存储不同的客服端信息
struct ADDR
{
    struct sockaddr_in cin;
    struct ADDR *next;
};

// 登录操作的函数
void do_login(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{
    // 先遍历链表 将新用户加入群聊的消息发给所有人
    struct ADDR *tmp = addr; // 记录链表头节点
    while (tmp->next != NULL)
    {
        tmp = tmp->next;
        if (-1 == sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(tmp->cin), sizeof(tmp->cin)))
        {
            perror("sendto error");
        }
    }
    // 将新用户的网络信息结构体 头插入链表
    struct ADDR *pnew = NULL;
    if (NULL == (pnew = (struct ADDR *)malloc(sizeof(struct ADDR))))
    {
        printf("malloc error\n");
        return;
    }
    pnew->cin = cin;
    pnew->next = addr->next;
    addr->next = pnew;
    return;
}

// 群聊操作的函数
void do_chat(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{
    // 遍历链表,将群聊消息发给除了自己之外的所有人
    struct ADDR *ptmp = addr;
    while (ptmp->next != NULL)
    {
        ptmp = ptmp->next;
        if (memcmp(&cin, &(ptmp->cin), sizeof(cin)))
        {
            // 不是自己 就发送数据
            sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(ptmp->cin), sizeof(ptmp->cin));
        }
    }
    return;
}

// 退出操作的函数
void do_quit(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{
    // 遍历链表 是自己就将自己在链表中删除
    // 不是自己 就发送 退出群聊的数据
    struct ADDR *ptmp = addr;
    struct ADDR *del = NULL;
    while (ptmp->next != NULL)
    {
        if (memcmp(&(ptmp->next->cin), &cin, sizeof(cin)))
        {
            // 不是自己
            ptmp = ptmp->next;
            strcat(buf.name,"-系统接管");
            sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(ptmp->cin), sizeof(ptmp->cin));
        }
        else
        {
            // 是自己
            del = ptmp->next;
            ptmp->next = del->next;
            free(del);
            del = NULL;
        }
    }
    return;
}

int main(int argc, char const *argv[])
{
    // 1、创建用于通信的套接字文件描述符
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sfd == -1)
    {
        perror("scoket error");
        return -1;
    }
    printf("sfd = %d\n", sfd); // 3
    // 2、绑定ip地址和端口号
    //  2.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); // ip地址

    // 2.2、 绑定
    if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");
    // 3、数据接收
    struct MSG buf; // 定义用于信息接收的变量

    // 定义用于接收客服端网络信息的变量
    struct sockaddr_in cin;          // 接收对端地址信息
    socklen_t addrlen = sizeof(cin); // 接收地址长度

    // 4、创建父子进程用于不同功能
    pid_t pid = 0;
    if (-1 == (pid = fork()))
    {
        perror("fork error");
        return -1;
    }
    if (0 == pid) // 子进程,用于信息的处理
    {
        // 创建保存客户端信息的链表头节点
        struct ADDR *addr;
        if (NULL == (addr = (struct ADDR *)malloc(sizeof(struct ADDR))))
        {
            printf("malloc error\n");
            return -1;
        }
        memset(addr, 0, sizeof(addr));
        addr->next = NULL;

        while (1)
        { // 循环收发数据
            // 清空容器,确保信息准确
            memset(&buf, 0, sizeof(buf));
            memset(&cin, 0, sizeof(cin));
            // 接收客户端发送的消息,存放在msg中
            if (-1 == recvfrom(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&cin, &addrlen))
            {
                perror("recvfrom error");
                return -1;
            }
            switch (buf.type)
            {         // 判断消息中的操作码,根据操作码执行对应操作
            case 'L': // 登录操作
                do_login(sfd, buf, addr, cin);
                break;
            case 'T': // 群聊操作
                do_chat(sfd, buf, addr, cin);
                break;
            case 'Q': // 退出操作
                do_quit(sfd, buf, addr, cin);
                break;
            }
        }
    }
    else // 父进程,用于发送系统信息
    {
        strcpy(buf.name, "系统消息");
        buf.type = 'T';
        while (1) // 循环在终端接收消息
        {
            memset(buf.msg, 0, sizeof(buf.msg));
            printf("输入信息:");
            fgets(buf.msg, 256, stdin);
            buf.msg[strlen(buf.msg) - 1] = 0;
            sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, addrlen);// 向子进程发送信息
        }
    }

    // 4、关闭文件描述符
    close(sfd);
    return 0;
}

2、客服端

#include <myhead.h>
#define SER_PORT 6666            // 与服务器保持一致
#define SER_IP "192.168.179.128" // 服务器ip地址

// 用于信息发送的结构体
struct msgTyp
{
    char type;     // 信息类型 L-》注册名 T-》聊天信息 Q-》退出
    char name[20]; // 注册名
    char msg[256]; // 聊天信息
};

int main(int argc, char const *argv[])
{
    // 1、 创建用于通信的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("cfd = %d\n", cfd);

    // 2、信息发送
    // 2.1数据结构体定义
    struct msgTyp buf;
    bzero(&buf, 0);

    // 2.2 填充服务器地址信息结构体
    struct sockaddr_in sin;                  // 接收对端地址信息
    sin.sin_family = AF_INET;                // 服务器的通信域
    sin.sin_port = htons(SER_PORT);          // 服务器的端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP); // 服务器的ip地址
    socklen_t seraddr_len = sizeof(sin);     // 服务器信息结构体大小

    // 2.3 注册
    buf.type = 'L'; // 指定消息类型
    printf("注册用户名:");
    fgets(buf.name, sizeof(buf.name), stdin);
    buf.name[strlen(buf.name) - 1] = 0;
    strcpy(buf.msg, "登录");

    // 向服务器发送登录信息
    sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);

    // 3 创建父子进程用于处理不同工作
    pid_t pid = 0;
    if (-1 == (pid = fork()))
    {
        perror("fork error");
        return -1;
    }
    // 子进程,用于接收信息
    if (0 == pid)
    {
        while (1)
        {
            if (-1 == recvfrom(cfd, &buf, sizeof(buf), 0, NULL, NULL))
            {
                perror("recvfrom error");
                return -1;
            }

            // 打印接收到的信息
            printf("[%s]:%s\n", buf.name, buf.msg);
        }
    }
    else if (0 < pid) // 父进程,用于向其他客服端发送信息
    {
        while (1)
        {
            bzero(&buf, 0); // 清空容器,以保证信息的准确性
            printf("输入信息:");
            fgets(buf.msg, 256, stdin);
            buf.msg[strlen(buf.msg) - 1] = 0;
            if (!strcmp(buf.msg, "quit"))
            {
                buf.type = 'Q';
                strcpy(buf.msg, "退出群聊");
                sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);
                break;
            }
            else
            {
                buf.type = 'T';
                // 发送信息
                sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);
            }
        }
        // 退出子进程
        kill(pid, SIGKILL);
        wait(NULL); // 阻塞回收子进程资源
    }

    // 3、关闭套接字
    close(cfd);
    return 0;
}

 

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

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

相关文章

设备实时数据采集:开启制造业智能化、自动化的新篇章

传统制造业在进行生产过程中&#xff0c;会涉及到设备实时数据采集需求&#xff0c;这些数据对于监控生产流程、优化生产效率、保证产品质量以及降低成本等方面至关重要。以下是一些常见的数据采集需求&#xff1a; 1.生产数据&#xff1a;包括生产数量、生产批次、生产速度等&…

Facebook与区块链:社交网络如何融入去中心化技术

随着区块链技术的飞速发展&#xff0c;去中心化理念逐渐渗透到各个领域&#xff0c;社交网络也不例外。作为全球领先的社交平台&#xff0c;Facebook在这一趋势下开始积极探索区块链技术的潜力&#xff0c;希望利用这一前沿技术来提升平台的安全性、透明度和用户控制权。本文将…

Maven-02.介绍安装

一.介绍 首先从本地仓库中寻找所需要的jar包&#xff0c;如果没有就从中央仓库中寻找。然后从中央仓库中下载使用。但是中央仓库的服务器在国外&#xff0c;因此速度和稳定性都不好&#xff0c;因此我们在中间设立远程仓库&#xff08;私服&#xff09;&#xff0c;远程仓库一般…

光伏气象站——提升光伏发电效率和稳定运行

光伏气象站作为现代光伏电站的必备组成部分&#xff0c;‌特别适用于地理分布广泛、‌气象条件复杂多变的地区&#xff0c;‌如山区、‌森林或分散的屋顶安装等。‌这些地方由于可能存在微气候差异&#xff0c;‌对光伏系统的运行效率和性能有着显著影响。‌因此&#xff0c;‌…

LeetCode:3148. 矩阵中的最大得分(DP Java)

目录 3148. 矩阵中的最大得分 题目描述&#xff1a; 实现代码与解析&#xff1a; DP 原理思路&#xff1a; 3148. 矩阵中的最大得分 题目描述&#xff1a; 给你一个由 正整数 组成、大小为 m x n 的矩阵 grid。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧…

STM32裸机和RTOS中的线程安全问题及STM32cubeMX中的线程安全策略

STM32线程安全问题 术语“线程” 和“多线程” 适用于裸机和基于RTOS的应用程序&#xff0c;线程安全问题并不只存在于基于RTOS的应用程序中&#xff1b;裸机应用程序中也存在这个问题&#xff0c;在裸机应用程序中&#xff0c;中断服务程序允许调用C库函数。线程安全问题可能…

『Z-Workshop』 The Graph workshop mini hackathon活动

Community Meetup In Hangzhou ZJUBCA 2024 求是 创新 概述 / OVERVIEW The Graph作为一个去中心化的查询协议&#xff0c;为区块链数据的索引和查询提供了强大的支持。我们希望通过这场黑客松&#xff0c;激发大家对区块链技术更深层次的探索和应用&#xff0c;共同推动这一…

第七十四:前端实现点击页面某个菜单跳转到对应的锚点功能

1.用js来实现 scrollIntoView方法 先定义个id或者class随意&#xff0c;因为我是循环好几个小模块所以用动态的来实现 点击的时候传对应的类名进行滑动 document.getElementById(item.variableCode).scrollIntoView({behavior:“smooth”}); 加上behavior:“smooth” 进行平…

为Linux/centos虚拟机已有硬盘扩容

为Linux已有硬盘扩容 旧盘扩容的大体流程与关键命令&#xff1a; 为虚拟机磁盘加容量&#xff1b; 为磁盘新容量分区&#xff08;fdisk&#xff09;&#xff1b; 将分区信息写入内核&#xff08;partx&#xff09;&#xff1b; 为分区创建物理卷&#xff08;pvcreate&#xff0…

电脑如何录屏?三款电脑录屏工具分享

电脑如何录屏&#xff1f;作为一个经常需要录制电脑屏幕大职场人&#xff0c;不是为了制作教程、记录会议&#xff0c;就是偶尔想自己做个游戏解说视频。市面上的录屏软件琳琅满目&#xff0c;经过一番尝试和比较&#xff0c;我选出了三款我个人认为表现不错的软件&#xff0c;…

Qt qss以及对话框

字体对话框的实现 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }void Widget::on_fontbtn_clicked() {bool ok;QFont ret…

开源的向量数据库Milvus

Milvus是一款开源的向量数据库&#xff0c;专为处理向量搜索任务而设计&#xff0c;尤其擅长处理大规模向量数据的相似度检索。 官网地址&#xff1a;https://milvus.io/ 以下是关于Milvus的详细介绍&#xff1a; 一、基本概念 向量数据库&#xff1a;Milvus是一款云原生向量…

pyinstaller打包vnpy项目

因为我写的软件主要是自己用&#xff0c;很少有打包的习惯&#xff0c;直接源代码部署&#xff0c;导致打包&#xff0c;以下记录一下给一个朋友做的&#xff0c;对vnpy的改写&#xff0c;实现实时读取信号文件&#xff0c;发现文件中信号改变就做出相应的交易动作&#xff0c;…

离线安装 MySQL 数据库系统并实现远程登录

MySQL 5.7.25 的安装包&#xff0c;存放在 /opt/software 目录下 详细步骤 一、离线安装 MySQL 数据库系统1. 解压安装包2. 安装 MySQL 组件3. 登录 MySQL&#xff08;1&#xff09;初始化 MySQL 的数据库&#xff08;2&#xff09;启动 MySQL 服务&#xff08;3&#xff09;登…

书生大模型学习笔记9 - LMDeploy 量化部署

LMDeploy 量化部署 InternLM 2.5 20b量化前部署W4A16 模型量化量化模型部署streamlit web InternLM 2.5 20b量化前部署 lmdeploy serve api_server \/root/learning/InternLM/XTuner/merged_20b \--model-format hf \--quant-policy 0 \--cache-max-entry-count 0.01\--server…

创建干净虚拟环境对YOLOV8进行打包

背景 基于Yolov8写了一个视频检测小demo&#xff0c;考虑后续要到项目上使用&#xff0c;所以研究了一下打包流程。使用的工具是Pyinstaller&#xff0c;在原有的环境下面打包发现&#xff0c;大小有6个多G。所以想再弄一个干净的环境&#xff0c;只安装需要的模块&#xff0c…

前端基础4

本节内容&#xff1a; 1.CSS的弹性布局&#xff0c;也称Flex布局 2.Vue2的生命周期 一、Flex布局 弹性布局是前端页面布局最常用的方式之一&#xff0c;通常使用四个属性。 1.创建盒子 先创建一个盒子并为其添加一些样式可以更直观的体验弹性布局&#xff0c;代码如下&#…

xcode如何编译python

1、找到Python位置&#xff1a; 终端输入&#xff1a;which python 获取python的安装位置&#xff0c;一般为/usr/bin/python。获取到这个路径方便使用它来搭建python的编译环境。 2、在Xcode中创建python程序 打开Xcode&#xff0c;新建工程&#xff08;ShiftCommandN&…

前端基础知识(一些基本标签的用法)

前端&#xff1a;html,css,javascript html:超文本结构化标记语言 使用角度 1、供显示的元素 2、供收集信息的元素 css层叠联样式单 选择器&#xff08;给谁做样式&#xff09; 盒子模型&#xff08;了解html元素内部结构&#xff09; 布局&#xff08;把元素进行摆布&a…

C语言 | Leetcode C语言题解之第352题将数据流变为多个不想交区间

题目&#xff1a; 题解&#xff1a; typedef struct SummaryRanges{int left,right;struct SummaryRanges *pre,*next; } SummaryRanges;/** Initialize your data structure here. */SummaryRanges* summaryRangesCreate() {SummaryRanges *head malloc(sizeof(SummaryRange…