UDP实现文件的发送、UDP实现全双工的聊天、TCP通信协议
我要成为嵌入式高手之3月7日Linux高编第十七天!!
————————————————————————————
回顾
重要程序
1、UDP实现文件的发送
发端:
#include "head.h"int main(void)
{int sockfd = 0;struct sockaddr_in recvaddr;ssize_t nsize = 0;int ret = 0;int fd = 0;char pathname[1024] = {0};char tmpbuff[1024] = {0};ssize_t nret;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(33333);recvaddr.sin_addr.s_addr = inet_addr("192.168.1.167");memset(pathname, 0, sizeof(pathname));gets(pathname);nsize = sendto(sockfd, pathname, strlen(pathname), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (nsize == -1){perror("fail to sendto");return -1;}fd = open(pathname, O_RDONLY);if (fd == -1){perror("fail to open");return -1;}printf("pathname: %s\n", pathname);while (1){usleep(10);nret = read(fd, tmpbuff, sizeof(tmpbuff));nsize = sendto(sockfd, tmpbuff, nret, 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (nsize == -1){perror("fail to sendto tmpbuff");return -1;}if (nret <= 0){break;}}sprintf(tmpbuff, "|__quit__|");nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff)+1, 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (nsize == -1){perror("fail to sendto tmpbuff");return -1;}printf("成功发送 %s 文件\n", pathname);close(fd);close(sockfd);return 0;
}
收端:
#include "head.h"int main(void)
{int ret = 0;int sockfd = 0;char tmpbuff[4096] = {0};struct sockaddr_in recvaddr;ssize_t nsize = 0;struct sockaddr_in sendaddr;socklen_t len = sizeof(sendaddr);sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1){perror("fail to socket");return -1;}recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(33333);recvaddr.sin_addr.s_addr = inet_addr("192.168.1.167");ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (ret == -1){perror("fail to bind");return -1;}nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&sendaddr, &len);if (nsize == -1){perror("fail to recvfrom");return -1;}// printf("%s:%d>>接受到%ld个字节:%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),nsize,tmpbuff);int fd = 0;char ch[1024]= {0};fd = open(tmpbuff,O_WRONLY | O_CREAT | O_TRUNC, 0664);if (fd == -1){perror("fail to fopen");return -1;}while(nsize != 0){memset(ch, 0, sizeof(ch));nsize = recvfrom(sockfd, ch, sizeof(ch), 0, (struct sockaddr *)&sendaddr, &len);if (nsize == -1){perror("fail to recvfrom");return -1;}if (!strcmp(ch,"1")){break;}write(fd,ch,nsize);printf("写入%ld字节\n",nsize);}printf("接受完成!\n");close(fd);close(sockfd);return 0;
}
2、UDP实现全双工的聊天
发送端
#include "head.h"char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
pthread_t tid_send;
pthread_t tid_recv;void *sendfun(void *arg)
{ssize_t nsize = 0;struct msgbuf sendmsg;while(1){memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = MSG_TYPE_CHAT;sprintf(sendmsg.name, "%s", name);gets(sendmsg.text); if (!strcmp(sendmsg.text, ".quit")){sendmsg.type = MSG_TYPE_END;}nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (nsize == -1){perror("fail to sendto");return NULL;}if (sendmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_recv);return NULL;
}void *recvfun(void *arg)
{struct msgbuf recvmsg;ssize_t nsize = 0;while(1){memset(&recvmsg, 0, sizeof(recvmsg));nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);if (-1 == nsize){perror("fail to recvfrom");return NULL;}if (recvmsg.type == MSG_TYPE_CHAT){printf("%s(%s:%d)>%s\n", recvmsg.name, RECV_ADDR, RECV_PORT, recvmsg.text);}else if (recvmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_send);return NULL;
}int main(void)
{ssize_t nsize = 0;struct msgbuf sendmsg;/*设置接收方信息*/recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);/*输入昵称*/printf("请输入您的昵称:\n");gets(name);/*创建套接字*/sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1){perror("fail to sockfd");return -1;}/*设置要发送的信息*/memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = MSG_TYPE_START;sprintf(sendmsg.name, "%s", name);/*发送信息*/nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (nsize == -1){perror("fail to sendto");return -1;}pthread_create(&tid_send, NULL, sendfun, NULL);pthread_create(&tid_recv, NULL, recvfun, NULL);pthread_join(tid_send, NULL);pthread_join(tid_recv, NULL);close(sockfd);return 0;
}
接收端
#include "head.h"char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;
pthread_t tid_send;
pthread_t tid_recv;void *sendfun(void *arg)
{ssize_t nsize = 0;struct msgbuf sendmsg;while(1){memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = MSG_TYPE_CHAT;sprintf(sendmsg.name, "%s", name);gets(sendmsg.text); if (!strcmp(sendmsg.text, ".quit")){sendmsg.type = MSG_TYPE_END;}nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));if (nsize == -1){perror("fail to sendto");return NULL;}if (sendmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_recv);return NULL;
}void *recvfun(void *arg)
{struct msgbuf recvmsg;ssize_t nsize = 0;while(1){memset(&recvmsg, 0, sizeof(recvmsg));nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);if (-1 == nsize){perror("fail to recvfrom");return NULL;}if (recvmsg.type == MSG_TYPE_CHAT){printf("%s(%s:%d)>%s\n", recvmsg.name, inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), recvmsg.text);}else if (recvmsg.type == MSG_TYPE_END){break;}}pthread_cancel(tid_send);return NULL;
}int main(void)
{char tmpbuff[1024] = {0};struct msgbuf recvmsg;int ret = 0;socklen_t addrlen = sizeof(sendaddr);/*设置接收方信息*/recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);/*输入昵称*/printf("请输入您的昵称:\n");gets(name);/*创建套接字*/sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1){perror("fail to sockfd");return -1;}ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == ret){perror("fail to bind");return -1;}/*设置要发送的信息*/memset(&recvmsg, 0, sizeof(recvmsg));/*接收信息*/ret = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, (struct sockaddr *)&sendaddr, &addrlen);if (ret == -1){perror("fail to recvfrom");return -1;}pthread_create(&tid_send, NULL, sendfun, NULL);pthread_create(&tid_recv, NULL, recvfun, NULL);pthread_join(tid_recv, NULL);pthread_join(tid_send, NULL);close(sockfd);return 0;
}
head.h
#ifndef _HEAD_H
#define _HEAD_H#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <stdlib.h>
#include <grp.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>struct msgbuf
{int type; //消息类型char name[32]; //昵称char text[32]; //消息
};#define MSG_TYPE_START 100 //开始聊天消息类型
#define MSG_TYPE_END 200 //退出聊天消息类型
#define MSG_TYPE_CHAT 300 //聊天消息类型
#define RECV_ADDR "192.168.1.172" //接收端地址
#define RECV_PORT 50000 //接收端端口#endif
学习笔记
TCP通信
TCP发端(客户端)
socket -> connect -> send / recv-> close
TCP收端(服务端)
socket -> bind -> listen -> accept -> send / recv -> close
1、connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:发起链接请求
参数:
sockfd:套接字的描述符
addr:目的地址存放空间首地址
addrlen:IP地址的大小
返回值:成功0,失败-1;
2、send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:
sockfd:套接字描述符
buf:发送数据空间的首地址
len:发送数据的长度
flags:属性默认为0
返回值:
成功返回实际发送字节数
失败返回-1;
3、recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据
参数:
sockfd:套接字描述符
buf:存放数据空间首地址
len:最大接收数据的长度
flags:属性默认0
返回值:
成功返回实际接收字节数,失败返回-1;
若对方退出,返回0
客户端:
#include "head.h"int main(void)
{int ret = 0;int sockfd = 0;struct sockaddr_in serveaddr;char tmpbuff[1024] = {0};ssize_t nsize = 0;sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}serveaddr.sin_family = AF_INET;serveaddr.sin_port = htons(50000);serveaddr.sin_addr.s_addr = inet_addr("192.168.1.101");ret = connect(sockfd, (struct sockaddr *)&serveaddr, sizeof(serveaddr));if (ret == -1){perror("fail to connect");return -1;}gets(tmpbuff);nsize = send(sockfd, tmpbuff, strlen(tmpbuff), 0);if (nsize == -1){perror("fail to send");return -1;}memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);if (nsize == -1){perror("fail to recv");return -1;}printf("RECV: %s\n", tmpbuff);close(sockfd);return 0;
}
4、listen
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:监听客户端发送的链接请求,不会阻塞
参数:
sockfd:套接字描述符
backlog:允许等待的尚未被处理的三次握手请求的最大个数
返回值:成功0,失败-1;
5、accept
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:
处理等待链接队列中的第一个链接请求,若没有人发送链接请求会阻塞等待,直到有连接请求
参数:
sockfd:套接字描述符
addr:存放IP地址的空间首地址
addrlen:存放IP地址大小空间首地址
返回值:
成功返回一个新的文件描述符
失败返回-1;
服务端:
#include "head.h"int main(void)
{int sockfd = 0;struct sockaddr_in serveaddr;int ret = 0;int confd = 0;ssize_t nsize = 0;char tmpbuff[1024] = {0};serveaddr.sin_family = AF_INET;serveaddr.sin_port = htons(50000);serveaddr.sin_addr.s_addr = INADDR_ANY;sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1){perror("fail to socket");return -1;}ret = bind(sockfd, (struct sockaddr *)&serveaddr, sizeof(serveaddr));if (ret == -1){perror("fail to bind");return -1;}ret = listen(sockfd, 10);if (-1 == ret){perror("fail to listen");return -1;}confd = accept(sockfd, NULL, NULL);if (-1 == confd){perror("fail to accept");return -1;}nsize = recv(confd, tmpbuff, sizeof(tmpbuff), 0);if (-1 == nsize){perror("fail to recv");return -1;}printf("RECV: %s\n", tmpbuff);memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);nsize = send(confd, tmpbuff, strlen(tmpbuff), 0);if (-1 == nsize){perror("fail to send");return -1;}close(confd);close(sockfd);return 0;
}
相关文章:

UDP实现文件的发送、UDP实现全双工的聊天、TCP通信协议
我要成为嵌入式高手之3月7日Linux高编第十七天!! ———————————————————————————— 回顾 重要程序 1、UDP实现文件的发送 发端: #include "head.h"int main(void) {int sockfd 0;struct sockaddr_i…...

Yocto - Project Quick Build
欢迎光临! 这篇简短的文档将向您介绍使用 Yocto 项目构建典型镜像的过程。本文还介绍了如何为特定硬件配置构建。您将使用 Yocto Project 构建一个名为 Poky 的参考嵌入式操作系统。 Welcome! This short document steps you through the process for a typical i…...

深入探讨C++中的可变参数列表(Variadic Templates)
文章目录 导言可变参数列表的基本用法使用std::initializer_list应用场景 导言 在C编程中,处理可变数量参数的能力是一种非常有用的功能。通过可变参数列表,你可以编写更加通用和灵活的函数,从而提高代码的可读性和重用性。本文将详细介绍C中…...

MS2548 国产自动方向控制、半双工 RS-485 收发器 替代MAX13487
MS2548 国产自动方向控制、半双工 RS-485 收发器 替代MAX13487 北京冠宇铭通科技有限公司 肖小姐 产品简述 MS2548 是一个 5V 供电、半双工 RS-485 收发器。 芯片具有自动换向控制功能,可用于隔离485 端口,驱动器输入与使能信号一起配合控制芯片的状态&…...

数据库大师之路:Oracle在线学习平台全指南!
介绍数据库是由甲骨文公司开发的一款关系数据库管理系统(RDBMS),在数据库领域具有领先地位,并且以其系统可移植性而闻名。以下是对Oracle数据库的详细介绍: 市场地位:Oracle数据库是目前世界上流行的关系数…...

如何在Windows系统部署Jellyfin Server并实现公网访问内网影音文件
文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…...

华为北向网管NCE开发教程(3)CORBA协议开发
华为北向网管NCE开发教程(1)闭坑选接口协议 华为北向网管NCE开发教程(2)REST接口开发 华为北向网管NCE开发教程(3)CORBA协议开发 如果你真的还有选择的余地,能用REST,尽量用REST&…...

【算法训练营】最长公共子序列,倒水问题,奶牛吃草(Python实现)
最长公共子序列 时间限制:1 sec 空间限制:256 MB 问题描述 给定两个 1 到 n 的排列 A,B (即长度为 n 的序列,其中 [1,n] 之间的所有数都出现了恰好一次)。 求它们的最长公共子序列长度。 输入格式 第一行一个整数 n &a…...

Armadillo:矩阵类、向量类、Cube类和泛型类
文章目录 矩阵类、向量类、Cube类和泛型类Mat<type>matcx_matCol<type>veccx_vecRow<type>rowveccx_rowvecCube<type>cubecx_cubefield<object_type>SpMat<type>sp_matsp_cx_mat运算符: − * % / ! < > <…...

【守护健康】小脑萎缩患者必备营养指南
当生活给予我们挑战,我们选择用科学和关爱予以回应。面对小脑萎缩这一难题,正确的营养补充不仅是一剂强心针,更是患者康复之路上的坚实伙伴。今天,让我们一起了解那些能够助力小脑萎缩患者的神奇维生素! 1. 维生素B群…...

lvs集群中NAT模式
群集的含义 由多台主机构成,但对外表现为一个整体,只提供一个访问入口,相当于一台大型的计算机。 横向发展:放更多的服务器,有调度分配的问题。 垂直发展:升级单机的硬件设备,提高单个服务器自身功能。 …...

FPGA——三速自适应以太网设计(2)GMII与RGMII接口
FPGA——以太网设计(2)GMII与RGMII 基础知识(1)GMII(2)RGMII(3)IDDR GMII设计转RGMII接口跨时钟传输模块 基础知识 (1)GMII GMII:发送端时钟由MAC端提供 下…...

【校园导航小程序】2.0版本 静态/云开发项目 升级日志
演示视频 【校园导航小程序】2.0版本 静态/云开发项目 演示 首页 重做了首页,界面更加高效和美观 校园指南页 新增了 “校园指南” 功能,可以搜索和浏览校园生活指南 地图页 ①弃用路线规划插件,改用SDK开发包。可以无阻通过审核并发布…...

深入揭秘Lucene:全面解析其原理与应用场景(二)
本系列文章简介: 本系列文章将深入揭秘Lucene,全面解析其原理与应用场景。我们将从Lucene的基本概念和核心组件开始,逐步介绍Lucene的索引原理、搜索算法以及性能优化策略。通过阅读本文,读者将会对Lucene的工作原理有更深入的了解…...

Java中synchronized关键字、ReentrantLock、volatile关键字是如何实现线程同步的。
在Java中,synchronized关键字、ReentrantLock和volatile关键字这三个是编程中常用于实现线程同步的机制,下面结合代码详细说明一下这三个关键字的用法。 1. synchronized关键字: synchronized关键字是Java语言提供的内置锁机制,…...

路由拦截器
路由拦截可以分为几种不同的类型,每种类型都有其特定的作用和适用场景。以下是常见的几种路由拦截类型及其用途: 身份验证拦截器: 作用: 检查用户是否已经登录或具有有效的身份认证,并根据认证状态决定是否允许用户访问…...

Springboot+vue的物业管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue的物业管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的物业管理系统,采用M(model)Vÿ…...

STM32的启动流程分析 和 一些底层控制的原理
阅读引言: 阅读本文之后, 你将对单片机, 甚至是嵌入式系统, 或者是传统的PC机系统的启动流程有一个大致的了解, 本文更加偏向于单片机的启动流程分析。 目录 一、基础知识 1.STM32系列的微控制器(mcu&…...

C#面:几种注释类型
三种常见的注释类型:单行注释、多行注释和 XML 注释。 单行注释: 以双斜线 // 开头,用于在一行中注释单个语句或代码块。单行注释会被编译器忽略,不会对程序的执行产生任何影响。 例如: // 这是一个单行注释 int a…...

#onenet网络请求http(GET,POST)
参考博文: POST: https://blog.csdn.net/qq_43350239/article/details/104361153 POST请求(用串口助手测试): POST /devices/1105985351/datapoints HTTP/1.1 api-key:AdbrV5kCRsKsRCfjboYOCVcF9FY Host:api.heclouds.com Con…...

零基础学习JS--基础篇--索引集合类
数组是由名称和索引引用的值构成的有序列表。 JavaScript 中没有明确的数组数据类型。但是,你可以使用预定义的 Array 对象及其方法来处理应用程序中的数组。Array 对象具有以各种方式操作数组的方法,例如连接、反转和排序。它有一个用于确定数组长度的…...

【硬件工程师面经整理25_AD】
文章目录 1 AD设计电路全流程2 ad和cadence区别-逻辑上的区别 1 AD设计电路全流程 软件AD or 模拟数字? 软件AD:AD设计电路全流程包括以下步骤:选择AD库和添加、画原理图、PCB布局、PCB布线、PCB打样、PCB加工 模拟数字: 需求分…...

神经网络的矢量化,训练与激活函数
我们现在再回到我们的神经元部分,来看我们如何用python进行正向传递。 单层的正向传递: 我们回到我们的线性回归的函数。我们每个神经元通过上述的方法,就可以得到我们的激发值,从而可以继续进行下一层。 我们用这个方法就可以得…...

3.7号freeRtoS
1. 串口通信 配置串口为异步通信 设置波特率,数据位,校验位,停止位,数据的方向 同步通信 在同步通信中,数据的传输是在发送端和接收端之间通过一个共享的时钟信号进行同步的。这意味着发送端和接收端的时钟需要保持…...

瑞芯微 | I2S-音频基础 -1
最近调试音频驱动,顺便整理学习了一下i2s、alsa相关知识,整理成了几篇文章,后续会陆续更新。 喜欢嵌入式、Li怒晓得老铁可以关注一口君账号。 1. 音频常用术语 名称含义ADC(Analog to Digit Conversion)模拟信号转换…...

Linux配置.bashrc文件导致各种命令(vim、sudo)失效。
Linux配置.bashrc文件导致各种命令(vim、sudo)失效。 起因是 nvcc-V一直报错:-bash:nvcc: command not found 踩坑记录:上网一查说是没有配置cuda的环境变量。于是去修改了bashrc文件,在最下面…...

Visual Studio 2022 Version 17.9 新功能
Visual Studio 2022 v17.9 为广大 C 开发者引入了一系列好用的新功能和改进优化。 内存布局 现在,你可以使用【内存布局,Memory Layout】功能以可视化的方式来查看对象,结构体及联合体的内存布局信息,这可比以前需要手动查看内存…...

ArrayList 和 LinkedList 的区别
ArrayList ArrayList 是基于动态数组实现的, 它使用一块连续的内存空间来存储元素,因此访问元素的速度非常快(时间复杂度为 O(1)), 但是,在插入或删除元素时,如果位置不在数组末尾࿰…...

VGG16-CF-VGG11实验报告
说明:VGG16和CF-VGG11是论文《A 3D Fluorescence Classification and Component Prediction Method Based on VGG Convolutional Neural Network and PARAFAC Analysis Method》使用的两种主要模型。其对应代码仓库提供了实验使用的数据集、平行因子分析结果和CNN模型。论文和…...

基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的按键扫描、数码管显示按键值、显示按键LED应用
基于STC12C5A60S2系列1T 8051单片机的TM1638键盘数码管模块的按键扫描、数码管显示按键值、显示按键LED应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍TM1638键盘…...