在Ubuntu18.04中的两个程序(基于C++)的UDP通信

此文章将展示两个C++应用程序,这个应用中都分别定义了作为Serve和Client的部分,便于相互发送和接收测试。

测试分为两部分,第一部分测试是字符串的发送和接收,第二部分测试是结构体的发送和接收(其实也是先转化为字符串发送,接收后再转化为结构体的方式)

使用者可对相应部分进行注释和取消注释,以分别测试这两个功能。

源文件:
在这里插入图片描述

~代码

Code1:这段代码用作发送(实际稍作修改后发送和接收都可)

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <typeinfo> 

using namespace std;
//创建新的套接字之前需要调用一个引入Ws2_32.dll库的函数,否则服务器和客户端连接不上
#pragma comment(lib,"ws2_32.lib")

struct TEST
{
	int test;
};
struct INFO
{
	int year;
	int month;
	int day;
	TEST test_struct;
	double temperature;
};

int main(int argc, char* argv[])
{
	struct sockaddr_in Server;				//创建服务端sockaddr_in结构体
	//建立一个数据报类型的UDP套接字  ******************//
	int serverSocket = socket(PF_INET, SOCK_DGRAM, 0); //配置模式,
	//设置服务器地址addrSrv和监听端口
	Server.sin_family = AF_INET;
	Server.sin_addr.s_addr = inet_addr("127.0.0.1"); //设置服务器主机ip地址(与接收方客户端的IP对应)
	Server.sin_port = htons(8001);					 //发送用的端口,可以根据需要更改


	//使用bind()函数绑定监听端口,将socket文件描述符sockSrv与地址类型变量(struct sockaddr_in )进行绑定
	//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	bind(serverSocket, (sockaddr *)&Server, sizeof(sockaddr));

	//*************************************************************************************************************//
	struct sockaddr_in Client;				//创建客户端sockaddr_in结构体
	int clientSocket = socket(PF_INET, SOCK_DGRAM, 0); //配置模式,
	Client.sin_family = AF_INET;
	Client.sin_addr.s_addr = inet_addr("127.0.0.3");
	Client.sin_port = htons(8001);


//*************************************************************************************************************//
	
	//创建发送和接受的结构体以及转化时用到的字符串,用作测试
	INFO sendinfo,recvinfo;
	char send_info_buf[100], recv_info_buf[100];
	//创建发送和接受的字符串,用作测试
	char sendbuf[100]= "How are you?", recvbuf[100];
	//对发送的结构体成员赋值
	sendinfo.year = 2021;
	sendinfo.month = 7;
	sendinfo.day = 27;
	sendinfo.test_struct.test = 10;
	sendinfo.temperature = 23.50;
	//将发送的结构体sendinfo转化为字符串send_info_buf
	memcpy(send_info_buf, &sendinfo, sizeof(sendinfo));
//************************************************************************************************************//

	while (1)
	{	
		usleep(2000000);
		//发送
			/*  
				int sendto(int s, const void* buf, int len, unsigned int flags, const struct sockaddr* to, int tolen);
				s:            接收端的socket描述符
				buf:    UDP数据报缓存区(包含待发送数据)
				len:     UDP数据报长度
				flags: 调用方式标志位(一般设置为0)
				to:      指向接收数据的主机地址信息的结构体,(sockaddr_in需类型转换);
				tolen:所指的结构体的长度
			*/	
			//字符串发送和打印所用语句
			//int t = sendto(clientSocket, sendbuf, sizeof(sendbuf), 0, (sockaddr*)&Client, sizeof(Client));	
			//cout << "sendto_len:  "<<t << endl<< endl;//若发送失败。则返回-1	
			//结构体发送和打印所用语句
			int t = sendto(clientSocket, send_info_buf, sizeof(send_info_buf)+1  , 0, (sockaddr*)&Client, sizeof(Client));
			cout << "sendto_len:  "<<t << endl<< endl;//若发送失败。则返回-1

		//接收
			/*  
				int recvfrom(int s, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen);
				s:       socket描述符
				buf:    UDP数据报缓存区(包含所要接受数据)
				len:    缓存区长度
				flags:  调用方式标志位(一般设置为0)
				from:   指向发送数据的客户端地址信息的结构体,(sockaddr_in需类型转换);
				fromlen:指针,指向from中结构体的长度
			*/

			//字符串接收和打印所用语句
			//socklen_t len = sizeof(sockaddr);
			//recvfrom(serverSocket, recvbuf, sizeof(recvbuf), 0, (sockaddr*)&Server, &len);
			//printf("%s\n\n", recvBuf);

			//结构体接收和打印所用语句
			//recvfrom(serverSocket, recv_info_buf, sizeof(recv_info_buf), 0, (sockaddr *)&Server, &len);
			//memcpy(&recvinfo, recv_info_buf, sizeof(recv_info_buf));
			//cout << "Today is  " << recvinfo.year << "." << recvinfo.month<<"." << recvinfo.day << endl;
			//cout << "The template is " << recvinfo.temperature << endl;
			//cout << "The struct-test number is " << recvinfo.test_struct.test << endl<< endl;
			
	}
	//closesocket(sockClient);
	close(serverSocket);
	return 0;
}

Code2:这段代码用作接收(实际稍作修改后发送和接收都可)

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <typeinfo> 

using namespace std;
//创建新的套接字之前需要调用一个引入Ws2_32.dll库的函数,否则服务器和客户端连接不上
#pragma comment(lib,"ws2_32.lib")

struct TEST
{
	int test;
};
struct INFO
{
	int year;
	int month;
	int day;
	TEST test_struct;
	double temperature;
};

int main(int argc, char* argv[])
{	
	struct sockaddr_in Server;				//创建服务端sockaddr_in结构体
	//建立一个数据报类型的UDP套接字  ******************//
	int serverSocket = socket(PF_INET, SOCK_DGRAM, 0); //配置模式,
	//设置服务器地址addrSrv和监听端口
	Server.sin_family = AF_INET;
	Server.sin_addr.s_addr = inet_addr("127.0.0.3"); //设置服务器主机ip地址(与接收方客户端的IP对应)
	Server.sin_port = htons(8001);					 //发送用的端口,可以根据需要更改
	//使用bind()函数绑定监听端口,将socket文件描述符sockSrv与地址类型变量(struct sockaddr_in )进行绑定
	//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	bind(serverSocket, (sockaddr *)&Server, sizeof(sockaddr));

	//*******************************************************************************************//
	struct sockaddr_in Client;				//创建客户端sockaddr_in结构体
	int clientSocket = socket(PF_INET, SOCK_DGRAM, 0); //配置模式,
	Client.sin_family = AF_INET;
	Client.sin_addr.s_addr = inet_addr("127.0.0.1");
	Client.sin_port = htons(8001);

//*******************************************************************************************************
	//创建发送和接受的结构体以及转化时用到的字符串,用作测试
	INFO sendinfo,recvinfo;
	char send_info_buf[100], recv_info_buf[100];
	//创建发送和接受的字符串,用作测试
	char sendbuf[100]= "Hello!", recvbuf[100];
	//对发送的结构体成员赋值
	sendinfo.year = 1999;
	sendinfo.month = 11;
	sendinfo.day = 20;
	sendinfo.test_struct.test = 10;
	sendinfo.temperature = 18.30;
	//将发送的结构体sendinfo转化为字符串send_info_buf
	memcpy(send_info_buf, &sendinfo, sizeof(sendinfo));
//********************************************************************************************************

	while (1)
	{	
		
		//发送
			/*  
				int sendto(int s, const void* buf, int len, unsigned int flags, const struct sockaddr* to, int tolen);
				s:     接收端的socket描述符
				buf:  UDP数据报缓存区(包含待发送数据)
				len:  UDP数据报长度
				flags:调用方式标志位(一般设置为0)
				to:   指向接收数据的主机地址信息的结构体,(sockaddr_in需类型转换);
				tolen:同所指的结构体的长度
			*/	
			//字符串发送和打印所用语句
			//int t = sendto(clientSocket, sendbuf, sizeof(sendbuf), 0, (sockaddr*)&Client, sizeof(Client));	
			//cout << "sendto_len:  "<<t << endl;//若发送失败。则返回-1	
			//结构体发送和打印所用语句
			//int t = sendto(clientSocket, send_info_buf, sizeof(send_info_buf)+1  , 0, (sockaddr*)&Client, sizeof(Client));
			//cout << "sendto_len:  "<<t << endl<<endl;//若发送失败。则返回-1

		//接收
			/*  
				int recvfrom(int s, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen);
				s:       socket描述符
				buf:    UDP数据报缓存区(包含所要接受数据)
				len:    缓存区长度
				flags:  调用方式标志位(一般设置为0)
				from:   指向发送数据的客户端地址信息的结构体,(sockaddr_in需类型转换);
				fromlen:指针,指向from中结构体的长度
			*/
			socklen_t len = sizeof(sockaddr);
			//字符串接收和打印所用语句
			//recvfrom(serverSocket, recvbuf, sizeof(recvbuf), 0, (sockaddr*)&Server, &len);
			//printf("%s\n\n", recvbuf);

			//结构体接收和打印所用语句
			recvfrom(serverSocket, recv_info_buf, sizeof(recv_info_buf), 0, (sockaddr *)&Server, &len);
			memcpy(&recvinfo, recv_info_buf, sizeof(recv_info_buf));
			cout << "Today is  " << recvinfo.year << "." << recvinfo.month<<"." << recvinfo.day << endl;
			cout << "The template is " << recvinfo.temperature << endl;
			cout << "The struct-test number is " << recvinfo.test_struct.test << endl<<endl;
	}
	close(clientSocket);
	//close(serverSocket);
	return 0;
}

~编译

可用以下命令编译对应源代码:

g++ Code1.cpp -o Code1
g++ Code2.cpp -o Code2

生成可执行文件:在这里插入图片描述若未安装g++,可用以下命令安装

sudo apt-get install g++

输入密码后按步骤提示即可安装

~执行

可用以下命令执行对应可执行文件:

./Code1
./Code2

~效果

在这里插入图片描述
反向的发送和接收可尝试后自行测试

  • 8
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ubuntu 18.04是一款非常流行的Linux操作系统,也是一款非常适合开发者使用的操作系统。我们可以通过以下步骤在Ubuntu 18.04上基于VSCode搭建C语言开发环境。 第一步:安装VSCode 首先我们要从官方网站上下载VSCode的安装包。下载完成后,打开终端,进入到下载的安装包所在的目录,执行以下命令以安装: ``` sudo dpkg -i <package-name>.deb ``` 这里的`<package-name>`需要替换成你下载下来的文件名。然后我们执行以下命令以安装VSCode: ``` sudo apt-get install -f ``` 第二步:安装C/C++插件 安装VSCode后,我们需要安装C/C++插件。我们可以通过以下步骤来安装: 1.打开VSCode,点击左侧菜单栏的“拓展”按钮; 2.在搜索框输入“C/C++”并点击搜索; 3.找到“C/C++”插件并安装。 此时,我们就已经成功地安装了C/C++插件。 第三步:安装C语言编译器 在Ubuntu 18.04,我们可以使用`gcc`编译器来编译C语言代码。我们可以通过以下命令安装: ``` sudo apt-get install build-essential ``` 此时,我们就已经成功地安装了C语言编译器。 第四步:在VSCode编写和运行C代码 我们可以通过以下步骤在VSCode编写和运行C代码: 1.打开VSCode,创建一个新的`.c`文件; 2.编写C代码; 3.保存代码,并在保存时指定一个文件名和一个后缀名,如`hello.c`; 4.打开终端,进入到保存的文件所在的目录; 5.使用以下命令编译代码: ``` gcc -o hello hello.c ``` 6.执行编译后程序: ``` ./hello ``` 此时,我们就可以在终端看到程序的输出了。 总结: 在Ubuntu 18.04上基于VSCode搭建C语言开发环境主要需要安装VSCode、C/C++插件和C语言编译器,然后在VSCode编写和运行C代码。对于初学者来说,以上步骤就可以满足基本的开发需求了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值