实现一个跨平台的mysock库(windows、linux)
源码下载
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
windows
各种平台的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.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);
}
实现一个跨平台的mysock库(windows、linux)的更多相关文章
- acl 是一个跨平台的网络通信库及服务器编程框架
acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库.通过该库,用户可以非常容易地编写支持多种模式( ...
- 使用Active Database Duplication创建跨平台Data Guard设置 (Windows/Linux) (Doc ID 881421.1)
Using Active Database Duplication to Create Cross Platform Data Guard Setup (Windows/Linux) (Doc ID ...
- .NET Core 跨平台 串口通讯 ,Windows/Linux 串口通讯,flyfire.CustomSerialPort 的使用
目录 1,前言 2,安装虚拟串口软件 3,新建项目,加入 flyfire.CustomSerialPort 4,flyfire.CustomSerialPort 说明 5,开始使用 flyfire.C ...
- SVN管理多个项目版本库 (windows,linux 通用)
SVN管理多个项目版本库: . 安装SVN服务器软件,路径: C:\Program Files\Subversion . 在D盘创建svn根目录D:\SVN-CM . 在D:\SVN-CM下创建SVN ...
- 跨平台的EVENT事件 windows linux
#ifndef _HIK_EVENT_H_ #define _HIK_EVENT_H_ #ifdef _MSC_VER #include <Windows.h> #define hik_e ...
- 跨平台的EVENT事件 windows linux(转)
#ifndef _HIK_EVENT_H_ #define _HIK_EVENT_H_ #ifdef _MSC_VER #include <Windows.h> #define hik_e ...
- Mysql跨平台(Windows,Linux,Mac)使用与安装
MySQL其实是一个跨平台的轻量级数据库,平时开发会用到很多.有写程序可能要跨平台开发,接下来我就介绍一下如何跨平台使用Mysql. 这里所谓的跨平台就是Windows,Linux,Mac共同用一套M ...
- 转:一个跨WINDOWS LINUX平台的线程类
来源:http://blog.csdn.net/dengxu11/article/details/7232681 继Windows下实现一个CThread封装类之后,这里我再实现一个跨WINDOWS ...
- windows linux—unix 跨平台通信集成控制系统
首先,我们可以用到这个开源的开发包: mdk(Micro-Development-Kit)微量级软件开发包,提供几个常用类,主要实现了一个高性能的并发服务器引擎 使用c++开发,是一个跨平台的开发包, ...
随机推荐
- 【原创】利用Windows系统日志统计员工每天上下班考勤时间
利用Windows系统日志统计员工每天上下班考勤时间(命令行参数为统计月份): using System; using System.Collections.Generic; using System ...
- replace() MySQL批量替换指定字段字符串
mysql replace实例说明: UPDATE tb1 SET f1=REPLACE(f1, 'abc', 'def'); REPLACE(str,from_str,to_str) 在字符串 st ...
- KindEditor Asp.net
最近在使用KindEditor,其中遇到三个问题: 1.textarea添加 runat="server" 后整个editor在运行的时候不能显示出来,我没找到原因,于是我就把ru ...
- 【和我一起学python吧】python的一些推荐
看到未名的几篇帖子 使我想起了和python的一些经历,于是写了一篇咚咚. 1 书籍: python的syntax足够简单,semantics也不复杂,不怎么会使人混乱,一般来说看自带的文档足够可以学 ...
- iOS 8 Xcode6 设置Launch Image 启动图片<转>
Step1 1.点击Image.xcassets 进入图片管理,然后右击,弹出"New Launch Image" 2.如图,右侧的勾选可以让你选择是否要对ipad,横屏,竖屏,以 ...
- mount失败
又一次遇到mount失败,提示文件系统类型错误.选项错误.有坏超级块等.之前是在ubuntu 14.04 lts desktop上挂载windows下共享文件夹遇到的.这次具体的环境如下:CentOS ...
- linux - 怎么自动填写有交互的shell脚本 - SegmentFault
linux - 怎么自动填写有交互的shell脚本 - SegmentFault TCL/Expect交互式自动化测试概要 - - ITeye技术网站 expect是一种基于TCL,能与交互式程序进行 ...
- 【转】Nginx系列(五)--nginx+tomcat实现负载均衡
原博文出于: http://blog.csdn.net/liutengteng130/article/details/47129909 感谢! Nginx占有内存少,并发能力强,事实上Nginx ...
- PLSQL Developer 常用设置及快捷键
1.登录后自动选中My Objects(已验证可用) 默认情况下,PLSQL Developer登录后,Brower里会选择all Objects,如果你登录的用户是DBA, 要展开tables目录, ...
- HDU 5680 zxa and set (数学 推导结论)
zxa and set 题目链接: http://acm.hust.edu.cn/vjudge/contest/121332#problem/G Description zxa has a set , ...