Linux与Windows的UDP通讯代码实现
2023-03-14 22:47:28 时间
简单实现Linux与Windows之间的UDP通信
如图所示:
在Linux下使用Makefile进行编译,Makefile代码如下:
CC = g++ SRCS = main.cpp udp.cpp OBJS = $(SRCS:.cpp=.o) EXEC = myapp start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) .cpp.o: $(CC) -o $@ -c $< -DMYLINUX //这里在Linux下参加编译定义一个宏以区别 clean: rm -rf $(OBJS)
由于Windows系统下使用UDP调用Windows特有的库函数,而在Linux下使用的却是Linux内嵌的udp相关函数,使用在各自系统编译的时候所用到的函数及代码会有一定的区别,并且C/C++混合编译在Windows下需要特别说明使用extern关键字,而在Linux下却不需要。所以通过定义一个宏在一套代码中进行区别,这样在不同平台下都能够进行编译使用。
具体代码如下:
main.cpp代码是没有区别的:
#include <iostream> #include "udp.h" using namespace std; int main(int argc, char* argv[]) { if(argc > 2) { Socket_send(argv[2]); } else { Socket_recv(); } return 0; }
接下来是udp.h头文件,这里就能看出区分:
#ifndef UDP_H #define UDP_H #ifndef MY_LINUX extern "C" { #endif int Socket_send(char *ip);//udp发送 int Socket_recv();//接收端 #ifndef MY_LINUX } #endif #endif // UDP_H
最后就是udp.c源文件代码:
#include <stdio.h> #ifdef MY_LINUX //Linux下编译需要包含以下头文件,具体通过man可查到 #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define SOCKET int //在Linux下SOCKET数据类型就是int类型,所以在这里替换 #else #include <winsock2.h> #endif #ifndef MY_LINUX int Socket_send(char *ip) { size_t vc = 0; //初始化socket char buf[1024] = {0};//传输使用的字符串 DWORD ver; WSADATA wsaData; ver = MAKEWORD(1,1);//调用wsastartup时告诉Windows使用的sock版本 WSAStartup(ver, &wsaData); //创建socket结构体 SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);//建立一个socket //创建结构体 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr));//初始化结构体 addr.sin_family = AF_INET;//代表使用的是TCP/IP的地址 addr.sin_port = htons(8080);//设置使用的端口号 addr.sin_addr.s_addr = inet_addr(ip);//自检查网口IP while(1) { memset(buf, 0, sizeof(buf)); gets(buf); if(buf[0] == '0') {//循环退出条件 break; } vc = sendto(st, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));//发送函数 } closesocket(st);//使用完socket要将其关闭 WSACleanup();//释放win下socket内部的相关资源 return vc; } int Socket_recv() { //初始化socket char buf[1024] = {0};//传输使用的字符串 size_t rc = 0; DWORD ver; WSADATA wsaData; ver = MAKEWORD(1,1);//调用wsastartup时告诉Windows使用的sock版本 WSAStartup(ver, &wsaData); //创建socket结构体 SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);//建立一个socket //创建结构体 struct sockaddr_in recvaddr; memset(&recvaddr, 0, sizeof(recvaddr));//初始化结构体 recvaddr.sin_family = AF_INET;//代表使用的是TCP/IP的地址 recvaddr.sin_port = htons(8080);//设置使用的端口号 recvaddr.sin_addr.s_addr = htonl(INADDR_ANY);//接收端采用任意的IP地址 if(bind(st, (struct sockaddr *)&recvaddr, sizeof(recvaddr)) > -1) { struct sockaddr_in sendaddr; memset(&sendaddr, 0, sizeof(sendaddr)); int len = sizeof(sendaddr); while(1) { memset(buf, 0, sizeof(buf)); rc = recvfrom(st, buf, sizeof(buf), 0, (struct sockaddr *)&sendaddr, &len); //rc = recv(st, buf, sizeof(buf), 0); printf("recvive = %s ", buf); } // printf("IP = %u ", sendaddr.sin_addr.s_addr); } closesocket(st);//使用完socket要将其关闭 WSACleanup();//释放win下socket内部的相关资源 return rc; } #else //编译Linux环境下的函数实现 int Socket_send(char *ip) { size_t vc = 0; //初始化socket char buf[1024] = {0};//传输使用的字符串 //创建socket结构体 SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);//建立一个socket //创建结构体 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr));//初始化结构体 addr.sin_family = AF_INET;//代表使用的是TCP/IP的地址 addr.sin_port = htons(8080);//设置使用的端口号 addr.sin_addr.s_addr = inet_addr(ip);//自检查网口IP while(1) { memset(buf, 0, sizeof(buf)); gets(buf); if(buf[0] == '0') {//循环退出条件 break; } vc = sendto(st, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));//发送函数 } close(st);//使用完socket要将其关闭 return vc; } int Socket_recv() { //初始化socket char buf[1024] = {0};//传输使用的字符串 size_t rc = 0; //创建socket结构体 SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);//建立一个socket //创建结构体 struct sockaddr_in recvaddr; memset(&recvaddr, 0, sizeof(recvaddr));//初始化结构体 recvaddr.sin_family = AF_INET;//代表使用的是TCP/IP的地址 recvaddr.sin_port = htons(8080);//设置使用的端口号 recvaddr.sin_addr.s_addr = htonl(INADDR_ANY);//接收端采用任意的IP地址 if(bind(st, (struct sockaddr *)&recvaddr, sizeof(recvaddr)) > -1) { struct sockaddr_in sendaddr; memset(&sendaddr, 0, sizeof(sendaddr)); socklen_t len = sizeof(sendaddr); while(1) { memset(buf, 0, sizeof(buf)); rc = recvfrom(st, buf, sizeof(buf), 0, (struct sockaddr *)&sendaddr, &len); //rc = recv(st, buf, sizeof(buf), 0); printf("recvive = %s ", buf); } // printf("IP = %u ", sendaddr.sin_addr.s_addr); } close(st);//使用完socket要将其关闭 return rc; } #endif
最后在Linux下通过make命令就能得到执行程序:
以上就是简单的Windows下UDP实现代码到Linux系统下的移植过程咯。
相关文章
- Wireguard笔记(三) lan-to-lan子网穿透和多网段并存
- Wireguard笔记(二) 命令行操作
- Centos7 和 Centos8 升级内核
- Keil MDK STM32系列(七) STM32F4基于HAL的PWM和定时器
- Keil MDK STM32系列(六) 基于抽象外设库HAL的ADC模数转换
- STM32F401+nRF24L01无线传输音频(对讲机原型)
- Keil MDK STM32系列(五) 使用STM32CubeMX创建项目基础结构
- Keil MDK STM32系列(四) 基于抽象外设库HAL的STM32F401开发
- Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发
- Keil MDK STM32系列(十) Ubuntu下的PlatformIO开发环境
- nRF24L01基于FIFO TX队列的发送性能优化
- phpBB3在Nginx反向代理中的X-Forwarded-For IP检查
- STC89C52驱动MAX7219LED点阵级联, 文字滚动效果
- STM32F407VET6烧录出现flash download failed target dll has been cancelled
- GCC项目的文件组织和编译步骤分解
- Ubuntu下使用PlatformIO开发STC89/STC12/Arduino
- 51单片机封装库HML_FwLib_STC89/STC11
- 用STM32F401和nRF24L01制作无线调速小车
- 在PWM控制下的直流有刷电机性能优化
- Github开始强制使用PAT(Personal Access Token)了