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;
}

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

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

相关文章

PHP在线图像处理程序:基于Photoshop的网页版图片处理源码

PHP在线PS修图网页版源码&#xff1a;实现照片图片处理的便捷工具 众所周知&#xff0c;许多朋友都喜欢使用PS进行图像编辑。然而&#xff0c;PS需要下载软件并对电脑配置要求较高。今天我们为大家带来一款基于浏览器的在线PS网页版源码&#xff0c;让您轻松实现在线P图和作图…

Kafka MQ 主题和分区

Kafka MQ 主题和分区 Kafka 的消息通过 主题 进行分类。主题就好比数据库的表&#xff0c;或者文件系统里的文件夹。主题可以被分为若干个 分区 &#xff0c;一个分区就是一个提交日志。消息以追加的方式写入分区&#xff0c;然 后以先入先出的顺序读取。要注意&#xff0c;由…

【论文阅读】Mamba:选择状态空间模型的线性时间序列建模(一)

文章目录 Mamba:选择状态空间模型的线性时间序列建模介绍状态序列模型选择性状态空间模型动机&#xff1a;选择作为一种压缩手段用选择性提升SSM 选择性SSM的高效实现先前模型的动机选择扫描总览&#xff1a;硬件感知状态扩展 Mamba论文 Mamba:选择状态空间模型的线性时间序列建…

软件测试入门

文章目录 一、入门1. 软件2. 软件基本组成3. 软件产生过程4. 软件测试5. 软件测试目的&#x1f3c6; 小结 二、测试主流技能1. 功能测试2. 自动化测试3. 接口测试4. 性能测试&#x1f3c6; 小结 三、测试分类1. 按测试阶段划分2. 按代码可见度划分&#x1f3c6; 小结 三、质量模…

数字人ai直播软件突破AI大模型技术,改变未来科技格局!

数字人AI直播软件在AI大模型技术上的突破&#xff0c;将不可避免地改变未来科技格局。这一突破让人们看到了AI技术的无限可能性&#xff0c;并为未来的科技发展打开了新的大门。 AI大模型技术是近年来人工智能领域的一个热点&#xff0c;它通过构建庞大、复杂的神经网络模型&a…

bug - poi getMergedRegion合并后的行列number错误

第一个CellRangeAddress 的Row number 应该是0&#xff0c;但是给出的是1。 其它的CellRangeAddress 与实际大致相差4-5不等&#xff0c;没有规律。 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>…

气象数据免费下载(超级好用)

你是不是做实验经常性的需要一些气象数据&#xff0c;例如PM2.5、相对湿度、月均温度等等…… 但是当你开始寻找数据时就遇到困难了&#xff0c;由于权限、数据网站之类的麻烦你会花费大量无用时间&#xff0c;甚至有时候一无所获得不偿失&#xff0c;这就很头疼了&#xff01;…

一篇了解电感的使用

一、电感理论基础 1.电感的定义 当电流通过线圈后&#xff0c;会产生磁场&#xff0c;磁感线穿过线圈&#xff0c;产生的磁通量与电流 i有如下关系&#xff1a; 将漆包线、纱包线或塑皮线等在绝缘骨架或磁心、铁心上绕制而成的器件&#xff0c;当线圈通过电流后&#xff0c;在…

工地安全反光衣穿戴监测报警摄像机

工地安全反光衣穿戴监测报警摄像机是为了提高工地施工人员的安全意识和监管效率而设计的。这种设备结合了反光衣、监测系统和报警摄像机的功能&#xff0c;可以有效减少工地事故的发生。 首先&#xff0c;工地安全反光衣是一种具有高度可见度的服装&#xff0c;能够使穿戴者在夜…

Unity中PICO实现移动交互

文章目录 前言一、在允许行走的地面加上对应的组件1、Teleportation Anchor 移动锚点2、Teleportation Area 移动区域 二、在 玩家&#xff08;需要移动的对象&#xff09;上挂载对应组件1、Teleportation Provider 被移动对象2、在 Teleportation Anchor 或 Teleportation Are…

一文学会搭建 cli 脚手架工具

文章目录 设置工具命令package.json bin 字段注释&#xff1a;#!/usr/bin/env node设置环境变量 接收命令选项参数process 实现commander 命令行交互&#xff1a;inquirer下载项目模板&#xff1a;download-git-repo执行额外命令&#xff1a;自动安装依赖child_processexeca 体…

FineReport决策报表Excel导出数据不全解决办法

一、首先建立决策报表 决策报表不带参数导出办法&#xff08;即没有参数面板&#xff09; 普通决策报表导出&#xff08;没有搜索面板&#xff09; 如果决策报表带参数&#xff08;即有搜索框&#xff09;&#xff0c;用上面的办法只能导出部分数据&#xff0c;数据不全 二、…

Go语言框架路由Controller控制器设计思路gin路由根据控制器目录分层生成路由地址

Controller设计好处 框架设计用controller分请求路由层级&#xff0c;应用从app目录开始对应请求url路由地址&#xff0c;这样设计师方便开发时候通过请求地址层级快速定位接口方法对应的代码位置。 例如api接口请求路径为&#xff1a;​​http://localhost:8110/​​busines…

C.C语言分支和循环语句

文章目录 一. 什么是语句 二. 分支语句&#xff08;选择结构&#xff09; 2.1. if 语句 2.1.1. 语法结构 2.1.2. 悬空else 2.1.3. 书写形式的对比 2.1.4. 练习 2.2. switch 语句 3.2.1. 语法结构 3.2.2. 在switch语句中的 break 3.2.3. default子句 3.2.4. 练习 三…

打造你的贪吃蛇游戏:HTML、CSS与JavaScript的完美结合

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

IPSEC VPPN实验

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

portainer管理远程docker和docker-swarm集群

使用前请先安装docker和docker-compose&#xff0c;同时完成docker-swarm集群初始化 一、portainer-ce部署 部署portainer-ce实时管理本机docker&#xff0c;使用docker-compose一键拉起 docker-compose.yml version: 3 services:portainer:container_name: portainer#imag…

Java高频面试之消息队列与分布式篇

有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 消息队列的基本作用&#xff1f; 异步通信&#xff1a;消息队列提供了异步通信的能力&#xff0c;发送方可以将消息发送到队列中&#xff0c;而无需等待接收方立即处理。发送方和接收方可以解耦&#x…

【数据结构】单链表的层层实现!! !

关注小庄 顿顿解馋(●’◡’●) 上篇回顾 我们上篇学习了本质为数组的数据结构—顺序表&#xff0c;顺序表支持下标随机访问而且高速缓存命中率高&#xff0c;然而可能造成空间的浪费&#xff0c;同时增加数据时多次移动会造成效率低下&#xff0c;那有什么解决之法呢&#xff…

Matlab|2机5节点牛拉法(含报告)

目录 主要内容 下载链接 主要内容 采用牛拉法计算2机5节点的潮流计算程序&#xff0c;程序迭代稳定&#xff0c;运行可靠&#xff0c;含报告资料。 下载链接