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

news/2024/5/17 19:52:06 标签: 网络, vim, linux, 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.niftyadmin.cn/n/5415750.html

相关文章

图论入门题题解

✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&#xff0c;麻烦点点赞哦&#x1f388; 所属专栏&#xff1a;刷题_脑子不好的小菜鸟的博客-CSDN博客 我的主页&#xff1a;脑子不好的小菜鸟 文章特点&#xff1a;关键点和步骤讲解放在 代码相应位置 拓扑排序 / 家谱…

粒子群算法优化支持向量机回归分析,PSO-SVM回归分析

目录 背影 支持向量机SVM的详细原理 SVM的定义 SVM理论 粒子群算法原理 SVM应用实例,粒子群算法优化支持向量机回归分析,PSO-SVM回归分析 代码 结果分析 展望 完整代码:粒子群算法优化支持向量机回归分析,PSO-SVM回归分析(代码完整,数据齐全)资源-CSDN文库 https://dow…

vscode 配置opengl (glut), lib链接可参考

这里假定你已经配置好基础的vscode c环境 json介绍 这里其实主要配置的3种json, vscode其实就是通过launch.json和tasks.json来自动生成指令的 launch.json 这个用于启动程序用的&#xff0c;但是由于其可以指定preLaunchTask-即在启动之前需要做什么事情&#xff0c;所以这…

DeepLearning in Pytorch|我的第一个NN-共享单车预测

目录 概要 一、数据准备 导入数据 数据可视化 二、设计神经网络 版本一 版本二&#xff08;正片&#xff09; 三、测试 小结 概要 我的第一个深度学习神经网络模型---利用Pytorch设计人工神经网络对某地区租赁单车的使用情况进行预测 输入节点为1个&#xff0c;隐含…

【漏洞复现】帮管客 CRM jiliyu SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

分享axios+MQTT简单封装示例

MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&#xff09;模式的"轻量级"通讯协议&#xff0c;该协议构建于TCP/IP协议上&#xff0c;由IBM在19…

剪枝例题一道

例题一 Code force round 我的思路&#xff0c;DFS遍历所有x&#xff0c;y&#xff0c;然后用set记录所有k&#xff0c;但是TLE了&#xff0c;最后发现&#xff0c;可以应用剪枝&#xff0c;如果一个x&#xff0c;y得出的k已经在set中存在了&#xff0c;那么不用再继续DFS后续…

排序算法——快速排序详细解释

快速排序&#xff08;Quicksort&#xff09;是一种常用的排序算法&#xff0c;其基本思想是通过分治的策略将一个数组分成两个子数组&#xff0c;然后分别对这两个子数组进行递归排序 一、快速排序算法的大致思路如下&#xff1a; 1、我们在对列表进行排序的过程中&#xff0c…