一、大家都知道主流的操作系统为Linux和windows,因此很多时候我们需要将编写的程序移植到不同的平台,这里的移植不是直接简单的删减代码,而是要保证程序能直接在两个
平台编译通过,从而保证代码的通用性,通常的做法是使用宏控。鉴于前面已经有啦windows下程序案例,本文简略的介绍如何将windows的udpdemo移植到Linux。
二、移植代码的实现
1.main.cpp 由于是通用cpp代码因此不做修改,代码如下:
#include <iostream>
#include "udp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int socket_send(void);
extern int socket_recv(void);
using namespace std;
int main(int argc,const char *argv[] ){
//若不传递参数,用作发送端,发送默认消息
if(argc < 2){
cout << "socket_send before ..." << endl;
socket_send();
}else{
//若传递参数作为接收端,接收并打印消息
cout << "socket_recv before ..." << endl;
socket_recv();
}
return 0;
}
2.udp.c 为了方便makefile管理在这里我们可以更改其文件名为udp.cpp,当然其中windows特有部分应该使用宏控隔离,修改后如下:
#ifdef MYLINUX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#else
#include <winsock2.h>
#endif
#include <string.h>
#include <stdio.h>
int socket_recv(void){
printf("recv before socket_recv starting...\n");
#ifndef MYLINUX
//初始化socket
DWORD ver;
WSADATA WSAData;
//在调用WSAStartup要告知Windows要使用什么版本的socket
ver = MAKEWORD(1,1);
WSAStartup(ver,&WSAData); //Windows 要求,只要使用socket,第一步必须调用这个函数
//初始化socket完成
#endif
/**
* @brief st
* params1: 协议族,指定socket使用哪一个协议族
* params2: 套接字类型,使用协议族中哪一个协议
* params3: 一般默认填写0
*/
#ifdef MYLINUX
int st;
socklen_t len;
#else
SOCKET st ;
int len;
#endif
st = socket(AF_INET,SOCK_DGRAM,0);//建立一个socket
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));//初始化addr
addr.sin_family = AF_INET;
addr.sin_port = htons(8090);
//addr.sin_addr.s_addr = inet_addr("192.168.1.102");
addr.sin_addr.s_addr = htonl(INADDR_ANY);//作为接收方,不需要指定具体的IP地址,接受主动的地址
if(bind(st,(struct sockaddr *)&addr,sizeof(struct sockaddr))){
printf("bind error...\n");
return -1;
} //当端口号和程序绑定
printf("recv before...\n");
char buf[1024]={0};
struct sockaddr_in src_addr;
len= sizeof(struct sockaddr);
memset(buf,0,sizeof(buf));
recvfrom(st,buf,sizeof(buf),0,(struct sockaddr *)&src_addr,&len);
printf("buf:%s src_ip:%s\n src_port:%d\n",buf,inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port));
#ifdef MYLINUX
close(st);
#else
closesocket(st);
WSACleanup();//释放win socket 的相关的资源
#endif
return 0;
}
int socket_send(void){
#ifndef MYLINUX
//初始化socket
DWORD ver;
WSADATA WSAData;
//在调用WSAStartup要告知Windows要使用什么版本的socket
ver = MAKEWORD(1,1);
WSAStartup(ver,&WSAData); //Windows 要求,只要使用socket,第一步必须调用这个函数
//初始化socket完成
#endif
/**
* @brief st
* params1: 协议族,指定socket使用哪一个协议族
* params2: 套接字类型,使用协议族中哪一个协议
* params3: 一般默认填写0
*/
#ifdef MYLINUX
int st;
#else
SOCKET st ;
#endif
st = socket(AF_INET,SOCK_DGRAM,0);//建立一个socket
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));//初始化addr
addr.sin_family = AF_INET;
addr.sin_port = htons(8090);
addr.sin_addr.s_addr = inet_addr("192.168.1.102");
char buf[1024]={0};
strcpy(buf,"welcome to dhu\n");
size_t rc = sendto(st,buf,strlen(buf)+1,0,(struct sockaddr *)&addr,sizeof(struct sockaddr));
#ifdef MYLINUX
close(st);
#else
closesocket(st);
WSACleanup();//释放win socket 的相关的资源
#endif
return 0;
}
3.udp.h 修改如下:
#ifndef UDP_H
#define UDP_H
#ifndef MYLINUX
extern "C"{
int socket_send(void);
int socket_recv(void);
}
#else
int socket_send(void);
int socket_recv(void);
#endif
#endif // UDP_H
4.Makefile 编写,由于Linux下没有安装IDE开发环境,所以Makefile需要手动添加CC=g++
SRCS=main.cpp\
udp.cpp
OBJS=$(SRCS:.cpp=.o)
EXEC=myudp
start:$(OBJS)
$(CC) -o $(EXEC) $(OBJS)
.cpp.o:
$(CC) -o $@ -c $^ -DMYLINUX
clean:
rm -rf $(OBJS) $(EXEC)
可以看出上面Makefile编译选项中传递了参数-DMYLINUX意思就是将生成一个宏MYLINUX传递给相关的.cpp文件,和cpp文件中#ifdef MYLINUX对应。
三、运行效果
这里让windows下myudp作为接收端,Linux下myudp作为发送端,结果如下:
buf:welcome to dhu
src_ip:192.168.1.107
src_port:39804
上述案例只是一个简单的移植过程,移植中我们采用宏控的方式,程序我们现在windows下编写,然后将编写好的程序拷贝到Linux下,编写makefile,然后逐个调错,错误调试调试完毕后,将代码拷贝至windows下验证,看能够编译运行如果成功,则移植完毕。