UDP实现文件的发送、UDP实现全双工的聊天、TCP通信协议

news2024/11/17 2:25:13

我要成为嵌入式高手之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;
}

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

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

相关文章

缩放算法优化步骤详解

添加链接描述 背景 假设数据存放在在unsigned char* m_pData 里面&#xff0c;宽和高分别是&#xff1a;m_nDataWidth m_nDataHeight 给定缩放比例&#xff1a;fXZoom fYZoom&#xff0c;返回缩放后的unsigned char* dataZoom 这里采用最简单的缩放算法即&#xff1a; 根据比…

【C语言】数据类型和变量

前言&#x1f49e;&#x1f49e; 啦啦啦~这里是土土数据结构学习笔记&#x1f973;&#x1f973; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所属专栏&#xff1a;C语言笔记 &#x1f4a5;欢迎大家&#x1f973;&#x1f973;点赞✨收藏&#x1f49…

【Node.js从基础到高级运用】二、搭建开发环境

Node.js入门&#xff1a;搭建开发环境 在上一篇文章中&#xff0c;我们介绍了Node.js的基础概念。现在&#xff0c;我们将进入一个更实际的阶段——搭建Node.js的开发环境。这是每个Node.js开发者旅程中的第一步。接下来&#xff0c;我们将详细讨论如何安装Node.js和npm&#…

将python编写的网站制作成docker镜像并上传到Github Packages上

文章目录 前言Docker安装docker注意事项 创建Dockerfile注意事项 构建 Docker 镜像运行 Docker 镜像 发布到Github Packages坑坑到位申请token的坑docker登录的坑给镜像添加标签的坑docker推送的坑 在Github Packages上查看总结 前言 还记得上一篇《借助ChatGPT使用Python搭建…

借助Aspose.html控件,在 Java 中将 URL 转换为 PDF

如果您正在寻找一种将实时 URL 中的网页另存为 PDF文档的方法&#xff0c;那么您来对地方了。在这篇博文中&#xff0c;我们将学习如何使用 Java 将 URL 转换为 PDF。从实时 URL转换HTML网页可以像任何其他文档一样保存所需的网页以供离线访问。将网页保存为 PDF 格式可以轻松突…

PandasAI—让AI做数据分析

安装 pip install pandasai !pip install --upgrade pandas pandasai 导入依赖项 import pandas as pdfrom pandasai import PandasAIfrom pandasai.llm.openai import OpenAI使用pandas创建一个数据框 df pd.DataFrame({"country": ["United States",…

MKS Type 631C 真空计说明详细内容查看图中目录

MKS Type 631C 真空计说明详细内容查看图中目录

【sw网络监控】通过snmp协议相关的snmp-exporter(收集交换机网络监控数据)+ promethus + grafana

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

C++异常处理机制

目录 一&#xff0c;传统C语言处理异常 二&#xff0c;C异常概念 三&#xff0c;使用 1. 自定义异常体系 2. 在函数调用链中异常栈展开匹配原则 3. 异常的重新抛出 四&#xff0c;异常规范 五&#xff0c;异常安全 六&#xff0c;C标准库的异常体系 七&#xff0c;异…

【开源】JAVA+Vue.js实现高校宿舍调配管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统展示四、核心代码4.1 查询单条个人习惯4.2 查询我的室友4.3 查询宿舍4.4 查询指定性别全部宿舍4.5 初次分配宿舍 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的…

liteIDE 解决go root报错 go: cannot find GOROOT directory: c:\go

liteIDE环境配置 我使用的liteIDE为 x36 5.9.5版本 。在查看–>选项 中可以看到 LiteEnv&#xff0c;双击LiteEnv &#xff0c;在右侧选择对应系统的env文件&#xff0c;我的是win64系统&#xff0c;所以文件名为win64.env 再双击 win64.env &#xff0c;关闭当前窗口&…

python淘宝网页爬虫数据保存到 csv和mysql(selenium)

数据库连接设置&#xff08;表和字段要提前在数据库中建好&#xff09; # 数据库中要插入的表 MYSQL_TABLE goods# MySQL 数据库连接配置,根据自己的本地数据库修改 db_config {host: localhost,port: 3306,user: root,password: ma*****6,database: may2024,charset: utf8mb…

TCP包头、TCP为什么安全可靠、UDP和TCP的区别、http协议

我要成为嵌入式高手之3月8日Linux高编第十八天&#xff01;&#xff01; __________________________________________________ 学习笔记 TPC包头 1、序号 发送端发送数据包的编号 2、确认号 已经确认接收到的数据的编号&#xff0c;只有当ACK为1时&#xff0c;该位才有用 …

简介maven核心:pom项目对象模型

Maven Maven 意思是知识的积累者&#xff0c;最初是为了简化 Jakarta Turbine 项目中的构建过程。有几个项目&#xff0c;每个项目都有自己的 Ant 构建文件&#xff0c;它们都略有不同。JAR 被检入 CVS。我们想要一种标准的方式来构建项目&#xff0c;清楚地定义项目的组成&am…

Jmeter 测试使用基本组件结构

JMeter简介 Apache组织开发的开源免费压测工具纯Java程序&#xff0c;跨平台性强源程序可以从网上下载高扩展性可对服务器、网络或对象模拟巨大的负载&#xff0c;进行压力测试可以用于接口测试支持分布式、多节点部署 JMeter安装 下载位置 官网https://jmeter.apache.org/ …

基于单片机的灭火机器人设计

目 录 摘 要 I Abstract II 引 言 1 1 系统方案设计 4 1.1 方案论证 4 1.2 灭火机器人系统工作原理 4 2 系统硬件设计 6 2.1 单片机 6 2.2 火焰探测系统设计 8 2.3 灭火系统设计 8 2.4 循迹模块设计 9 2.5 电机驱动模块 10 3 系统软件设计 12 3.1 系统软件开发环境 12 3.2 系统…

防御保护 IPSEC VPPN实验

实验背景&#xff1a;FW1和FW2是双机热备 主备备份模式。 实验要求&#xff1a;在FW5和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要配置FW1主设…

STM32标准库——(20)WDG看门狗

1.WDG简介 独立看门狗(IWDG)由专用的低速时钟(LSI)驱动&#xff0c;即使主时钟发生故障它也仍然有效。窗口看门狗由从APB1时钟分频后得到的时钟驱动&#xff0c;通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作 2.IWDG框图 它的结构和定时器是非常相似的&#xf…

打印机项目需求

打印机项目需求 工作情况如下 我拿着一张带有二维码的纸张对准“打印机的摄像头”“打印机的摄像头”解析我的二维码假如解析后的二维码内容是&#xff1a;24030924发送一个http请求&#xff1a;https://…/getMessage?code24030924外部服务器会返回一个json数据{‘地址’:‘…

Python编程实验六:面向对象应用

目录 一、实验目的与要求 二、实验内容 三、主要程序清单和程序运行结果 第1题 第2题 四、实验结果分析与体会 一、实验目的与要求 &#xff08;1&#xff09;通过本次实验&#xff0c;学生应掌握类的定义与对象的创建、类的继承与方法的覆盖&#xff1b; &#xff08;2…