红联Linux门户
Linux帮助

实现一个跨平台的mysock库(windows、linux)

发布时间:2016-04-07 10:05:15来源:linux网站作者:phlsheji

源码下载:http://download.csdn.net/detail/waldmer/8791683


1.首先确定自己的操作系统为32位还是64位:

root@bfq:~/mysock# uname -a

Linux bfq 3.11.0-26-generic#45~precise1-Ubuntu SMP Tue Jul 15 04:02:35 UTC 2014x86_64x86_64 x86_64 GNU/Linux


2.编写測试程序:

root@bfq:~/mysock# vim test.c

#include <stdio.h>

int main()

{
printf("sizeof(char *)=%d\n",sizeof(char *));

return 0;

}

编译、运行:

root@bfq:~/mysock# gcc test.c

root@bfq:~/mysock# file a.out

a.out: ELF64-bitLSB executable, x86-64, version 1 (SYSV), dynamically linked (uses sharedlibs), for GNU/Linux 2.6.24,BuildID[sha1]=0x69d02236045c81b597e24cb143cfca5909987b80, not stripped

root@bfq:~/mysock# ./a.out

sizeof(char *)=8

root@bfq:~/mysock# gcc test.c-m32

root@bfq:~/mysock# file a.out

a.out: ELF32-bitLSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses sharedlibs), for GNU/Linux 2.6.24,BuildID[sha1]=0x668431a373c94667857a83c2d92929e8b57cff58, not stripped

root@bfq:~/mysock# ./a.out

sizeof(char *)=4

使用-m32来使得gcc编译32位程序(在x86_64系统上),使用-m elf_i386參数可以使得64位的ld可以兼容32位的库


3.跨平台代码分析

编译:

root@bfq:~/mysock#ls

libmysock64.so makefile-lib32 makefile-lib64  makefile-win mysock.c  mysock.h

root@bfq:~/mysock#make -f makefile-lib32

gcc-Wall -D__UNIX -g -m32 -fPIC -o mysock.o -c mysock.c

gcc -m32 -shared -o libmysock32.so mysock.o

root@bfq:~/mysock#file libmysock32.so

libmysock32.so:ELF32-bit LSB shared object, Intel 80386,version 1 (SYSV), dynamically linked,BuildID[sha1]=0x18b8a6de746679cccfb10306d6bc62955e3566f4, not stripped

root@bfq:~/mysock#

root@bfq:~/mysock#make -f makefile-lib64

gcc-Wall -D__UNIX -g -fPIC -o mysock.o -c mysock.c

gcc-shared -o libmysock64.so mysock.o

root@bfq:~/mysock#ls

libmysock64.so makefile-lib32 makefile-lib64  makefile-win mysock.c  mysock.h mysock.o

root@bfq:~/mysock#file libmysock64.so

libmysock64.so:ELF64-bit LSB shared object, x86-64, version 1(SYSV), dynamically linked,BuildID[sha1]=0xbec5736775c33f27fe81e88c98f1c26a1edf97b9, not stripped

源代码结构:

linux

实现一个跨平台的mysock库(windows、linux)

windows

实现一个跨平台的mysock库(windows、linux)


各种平台的makefile

.SUFFIXES: .c .o
CC=gcc
SRCS=mysock.c
   
OBJS=$(SRCS:.c=.o)
EXEC=libmysock64.so
.c.o:
$(CC) -Wall -D__UNIX -g -fPIC -o $@ -c $<
all: $(OBJS)
$(CC) -shared -o $(EXEC) $(OBJS)
clean:
rm -rf $(OBJS) $(EXEC)

.SUFFIXES: .c .o
CC=gcc
SRCS=mysock.c
   
OBJS=$(SRCS:.c=.o)
EXEC=libmysock32.so
.c.o:
$(CC) -Wall -D__UNIX -g -m32 -fPIC -o $@ -c $<
all: $(OBJS)
$(CC)  -m32 -shared -o $(EXEC) $(OBJS)
clean:
rm -rf $(OBJS) $(EXEC)

利用vs开发工具本身能够编译出lib和dll。

实现一个跨平台的mysock库(windows、linux)

实现一个跨平台的mysock库(windows、linux)

mysock.h

#ifndef __MYSOCK_H
#define __MYSOCK_H

#ifdef __cplusplus
extern "C" {
#endif

//linux下设置进程进入daemon状态。windows无效
void set_daemon();

//windows下调用的初始化socket环境。linux不须要
void init_socket();

//windows下调用的释放socket环境。linux不须要
void free_socket();

//将域名转化为IP,domain代表域名,返回值为struct in_addr的s_addr成员
unsigned int domain2ip(const char *domain);

//建立一个socket。
//status = 1 is TCP, other is UDP。返回值>=0代表成功建立的socket句柄。-1失败
int create_socket(int status);

//关闭由create_socket创建的socket,
//sock为create_socket函数返回的socket句柄
void close_socket(int sock);

//为socket绑定一个端口号
//sock为create_socket函数返回的socket句柄。port为要绑定的端口号。返回值=0成功。-1失败
int bind_socket(int sock, unsigned short port);

//使用UDP协议接收数据
//sock为create_socket函数返回的socket句柄,buf为接收数据缓冲区。 bufsize为缓冲区大小(单位:字节), srcIP为数据来源IP地址。返回值>0成功接收数据字节数,=0连接正常关闭,-1失败
int udp_recv(int sock, char *buf, size_t bufsize, char *srcIP);

//使用UDP协议发送数据
//sock为create_socket函数返回的socket句柄。buf为发送数据缓冲区。 bufsize为发送数据大小(单位:字节)。destIP为发送目的IP地址,port为发送目的端口号 。返回值>0成功发送数据字节数,=0连接正常关闭,-1失败
int udp_send(int sock, const char *destIP, unsigned short port, const char *buf, size_t bufsize);

//使用TCP协议接收数据之前须要先listen
//sock为create_socket函数返回的socket句柄。返回值=0成功,-1失败
int tcp_listen(int sock);

//使用TCP协议接收来自client的链接
//sock为create_socket函数返回的socket句柄, srcIP为来自client的IP地址。返回值>0代表来自client的socket句柄,-1失败
int tcp_accept(int sock, char *srcIP);

//使用TCP协议连接到指定的服务器
//sock为create_socket函数返回的socket句柄,destIP为来自服务端端的IP地址。port为服务端的端口号。返回值=0成功,-1失败
int tcp_connect(int sock, const char *destIP, unsigned short port);

//使用TCP协议接收数据
//sock为create_socket函数返回的socket句柄。buf为接收数据缓冲区。 bufsize为缓冲区大小(单位:字节)。返回值>0成功接收数据字节数。=0连接正常关闭,-1失败
int tcp_recv(int sock, char *buf, size_t bufsize);

//使用TCP协议发送数据
//sock为create_socket函数返回的socket句柄,buf为发送数据缓冲区。 bufsize为发送数据大小哦(单位:字节)。返回值>0成功发送数据字节数,=0连接正常关闭,-1失败
int tcp_send(int sock, const char *buf, size_t bufsize);

////////////////////////////////下面为app函数//////////////////////////

//使用UDP协议接收数据
//buf为接收数据缓冲区, bufsize为缓冲区大小(单位:字节), port为接收数据的端口号,srcIP为数据来源IP地址。返回值>0成功接收数据字节数。=0连接正常关闭。-1失败
int app_udp_recv(char *buf, size_t bufsize, unsigned short port, char *srcIP);

//使用UDP协议发送数据
//buf为发送数据缓冲区。 bufsize为发送数据大小(单位:字节),destIP为发送目的IP地址,port为发送目的端口号 。返回值>0成功发送数据字节数,=0连接正常关闭。-1失败
int app_udp_send(const char *destIP, unsigned short port, const char *buf, size_t bufsize);

//使用TCP协议client连接到指定的服务端
//destIP为来自服务端的IP地址,port为服务端的端口号。返回值=0成功,-1失败
int app_client_connect(const char *destIP, unsigned short port);

//断开clientTCP连接
void app_client_close();

//断开服务端TCP连接
void app_server_close();

//使用TCP协议client接收数据
//buf为接收数据缓冲区。bufsize为缓冲区大小(单位:字节)。返回值>0成功接收数据字节数,=0连接正常关闭。-1失败
int app_client_recv(char *buf, size_t bufsize);

//使用TCP协议client发送数据
//buf为发送数据缓冲区。 bufsize为发送数据大小哦(单位:字节)。

返回值>0成功发送数据字节数,=0连接正常关闭,-1失败
int app_client_send(const char *buf, size_t bufsize);


//使用TCP协议。建立服务端socket
//參数port为服务端端口号,返回值=0成功,-1失败
int app_server_create(unsigned short port);

//使用TCP协议服务端接收数据
//buf为接收数据缓冲区。bufsize为缓冲区大小(单位:字节),srcIP为clientIP地址。

返回值>0成功接收数据字节数。=0连接正常关闭。-1失败
int app_server_recv(char *buf, size_t bufsize, char *srcIP);

//使用TCP协议服务端发送数据
//buf为发送数据缓冲区, bufsize为发送数据大小哦(单位:字节)。返回值>0成功发送数据字节数。=0连接正常关闭,-1失败
int app_server_send(const char *buf, size_t bufsize);

#ifdef __cplusplus
}
#endif

#endif


mysock.c

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#ifndef __UNIX
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable:4996)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#endif

//假设编译动态库。须要把#define STATIC_LIB凝视
#define STATIC_LIB

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void set_daemon()
{
#ifdef __UNIX
pid_t pid, sid;
pid = fork();
if (pid < 0)
{
exit(-1);
}
if (pid > 0)
{
exit(0);
}

if ((sid = setsid()) < 0)
{
exit(-1);
}
#endif
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void init_socket()
{
#ifndef __UNIX
unsigned short ver;
WSADATA wsaData;
ver = MAKEWORD(1, 1);
WSAStartup(ver, &wsaData);
#endif
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void free_socket()
{
#ifndef __UNIX
WSACleanup();
#endif
}


#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
unsigned int domain2ip(const char *domain)
{
struct hostent *iphost = gethostbyname(domain);
if (iphost)
{
struct in_addr *p = (struct in_addr *)iphost->h_addr_list[0];
if (p)
return p->s_addr;
}
return 0;
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int create_socket(int status)
{
#ifndef __UNIX
char on = 1;
#else
int on = 1;
#endif
int st = 0;
if (status == 1)
{
st = socket(AF_INET, SOCK_STREAM, 0);//建立TCP socket
setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));//设置socket地址可重用
}
else
{
st = socket(AF_INET, SOCK_DGRAM, 0);//建立UDP socket
setsockopt(st, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));//设置能够发送udp广播消息
}
return st;
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void close_socket(int sock)
{
#ifndef __UNIX
closesocket(sock);
#else
close(sock);
#endif
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int bind_socket(int sock, unsigned short port)
{
struct sockaddr_in recv_addr;
memset(&recv_addr, 0, sizeof(recv_addr));
recv_addr.sin_family = AF_INET;
recv_addr.sin_port = htons(port);//指定port为要连接的端口号
recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//指定接收端IP地址为随意
return bind(sock, (struct sockaddr *) &recv_addr, sizeof(recv_addr));
}


#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int udp_recv(int sock, char *buf, size_t bufsize, char *srcIP)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
#ifndef __UNIX
int len = sizeof(addr);
#else
socklen_t len = sizeof(addr);
#endif
unsigned int rc = recvfrom(sock, buf, bufsize, 0, (struct sockaddr *) &addr, &len);//接收到来自srcIP的消息
//strcpy(srcIP, inet_ntoa(addr.sin_addr));
unsigned char *c = (unsigned char *)&addr.sin_addr.s_addr;
sprintf(srcIP, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
return rc;
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int udp_send(int sock, const char *destIP, unsigned short port, const char *buf, size_t bufsize)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);//指定port为要连接的端口号
//addr.sin_addr.s_addr = inet_addr(destIP);//指定IP为要连接的IP地址
addr.sin_addr.s_addr = domain2ip(destIP);
return sendto(sock, buf, bufsize, 0, (struct sockaddr *) &addr, sizeof(addr));//向指定IP发送消息
}


#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int tcp_listen(int sock)
{
return listen(sock, 20);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int tcp_accept(int sock, char *srcIP)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
#ifndef __UNIX
int len = sizeof(addr);
#else
socklen_t len = sizeof(addr);
#endif
int st = accept(sock, (struct sockaddr *) &addr, &len);
//strcpy(srcIP, inet_ntoa(addr.sin_addr));
unsigned char *c = (unsigned char *)&addr.sin_addr.s_addr;
sprintf(srcIP, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
return st;

}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int tcp_connect(int sock, const char *destIP, unsigned short port)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);//指定port为要连接的端口号
//addr.sin_addr.s_addr = inet_addr(destIP);//指定IP为要连接的IP地址
addr.sin_addr.s_addr = domain2ip(destIP);
return connect(sock, (struct sockaddr *) &addr, sizeof(addr));//连接到指定IP
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int tcp_recv(int sock, char *buf, size_t bufsize)
{
return recv(sock, buf, bufsize, 0);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int tcp_send(int sock, const char *buf, size_t bufsize)
{
return send(sock, buf, bufsize, 0);
}

////////////////////////////////下面为app函数//////////////////////////

static int is_init = 0;
static int udp_recv_sock = -1;
static int udp_send_sock = -1;
static int tcp_client_sock = -1;
static int tcp_server_sock = -1;
static int tcp_list_sock = -1;

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_udp_recv(char *buf, size_t bufsize, unsigned short port, char *srcIP)
{
if (is_init == 0)
{
init_socket();
is_init = 1;
}
if (udp_recv_sock != -1)
close_socket(udp_recv_sock);

udp_recv_sock = create_socket(0);
int rc = bind_socket(udp_recv_sock, port);
if (rc < 0)
return rc;

return udp_recv(udp_recv_sock, buf, bufsize, srcIP);
}


#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_udp_send(const char *destIP, unsigned short port, const char *buf, size_t bufsize)
{
if (is_init == 0)
{
init_socket();
is_init = 1;
}
if (udp_send_sock == -1)
{
udp_send_sock = create_socket(0);
}

return udp_send(udp_send_sock, destIP, port, buf, bufsize);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_client_connect(const char *destIP, unsigned short port)
{
if (is_init == 0)
{
init_socket();
is_init = 1;
}

if (tcp_client_sock != -1)
close_socket(tcp_client_sock);

tcp_client_sock = create_socket(1);
return tcp_connect(tcp_client_sock, destIP, port);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void app_client_close()
{
if (tcp_client_sock != -1)
{
close_socket(tcp_client_sock);
tcp_client_sock = -1;
}
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
void app_server_close()
{
if (tcp_server_sock != -1)
{
close_socket(tcp_server_sock);
tcp_server_sock = -1;
}
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_client_recv(char *buf, size_t bufsize)
{
return tcp_recv(tcp_client_sock, buf, bufsize);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_client_send(const char *buf, size_t bufsize)
{
return tcp_send(tcp_client_sock, buf, bufsize);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_server_create(unsigned short port)
{
if (is_init == 0)
{
init_socket();
is_init = 1;
}
if (tcp_list_sock != -1)
{
close_socket(tcp_list_sock);
}

tcp_list_sock = create_socket(1);
int rc = bind_socket(tcp_list_sock, port);
if (rc == -1)
return rc;

return tcp_listen(tcp_list_sock);
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_server_recv(char *buf, size_t bufsize, char *srcIP)
{
static char IP[100];
if (tcp_server_sock <= 0)
{
memset(IP, 0, sizeof(IP));
tcp_server_sock = tcp_accept(tcp_list_sock, IP);
}
strcpy(srcIP, IP);
int rc = tcp_recv(tcp_server_sock, buf, bufsize);
if (rc <= 0)
app_server_close();
return rc;
}

#ifndef __UNIX
#ifndef STATIC_LIB
__declspec(dllexport)
#endif
#endif
int app_server_send(const char *buf, size_t bufsize)
{
return tcp_send(tcp_server_sock, buf, bufsize);
}


本文永久更新地址:http://www.linuxdiyf.com/linux/19573.html