将TCP 和UDP封装成动态库

my_socket.h

#ifndef __MY_SOCKET_H__
#define __MY_SOCKET_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define IN
#define OUT
#define IN_OUT
#define MY_TCP 1
#define MY_UDP 2
typedef struct sockaddr* pSA ;
typedef struct sockaddr_in SA ;
#define MY_ASSERT(flag,msg) ( (flag) ? NULL : ( fprintf(stdout,msg), exit(EXIT_FAILURE) ) )   // NULL代表什么也不做

void my_socket(OUT int *local_sfd, int protocal, char *local_ip, int local_port);
void my_listen(int local_sfd, int backlog);
void my_accept(OUT int *peer_sfd, int local_sfd, OUT pSA peer_addr, IN_OUT int *addr_len );
void my_connect(int local_sfd, pSA peer_addr, int addr_len);
void my_recv(OUT int *recv_len, int peer_sfd, IN_OUT void *base, int len);
void my_send(OUT int *send_len, int peer_sfd, void *base, int len);
void my_recvfrom(OUT int *recvfrom_len, int peer_sfd, IN_OUT void *base, int len, OUT pSA peer_addr, IN_OUT int *addr_len);
void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  pSA peer_addr, int addr_len);
void my_close(int sfd);
#endif

my_socket.c
/* 本代码用于在一台主机上模拟socket通信。因此IP地址对于server和client而言是一样的。
 * 为了简化代码,此处即使是客户端,也提前分配好端口号。事实上,主动方的端口号可以由系统分配,不用提前绑定
 * --> 无论server或者client,都会预先绑定本地socket */

/* 本代码local_sfd代表本地socket描述符。
 * 对于服务器而言,就是用于监听的socket; 对于客户端而言就是用于通信的socket
 * peer_sfd,代表与对方通信的socket描述符。
 * 对于服务器而言,由accept以传出参数形式返回;对于客户端而言,就是本地socket */

#include "my_socket.h"

void my_socket(OUT int *local_sfd, int protocal, char *local_ip, int local_port)
{
    MY_ASSERT(protocal == MY_TCP || protocal == MY_UDP, "wrong arg! protocal is MY_TCP or MY_UDP! \n");
    /* 创建本地socket */
    if(protocal == MY_TCP)
    {
        MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_STREAM, 0)), "tcp_socket init falure!\n");
    }else if(protocal == MY_UDP)
    {
        MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_DGRAM, 0)),  "udp_socket init failure!\n");
    }
    /* 将本地联系方式bind到本地socket */
    SA local_addr;
    memset(&local_addr, 0, sizeof(SA));
    local_addr.sin_family      = AF_INET;
    local_addr.sin_port        = htons(local_port);
    local_addr.sin_addr.s_addr = inet_addr(local_ip);
    MY_ASSERT( 0 == bind(*local_sfd, (pSA)&local_addr, sizeof(SA)), "bind failure!\n");
}

/*----------------------------- 以下针对TCP ----------------------------------------------------- */

/* server: listen + accept */
void my_listen(int local_sfd, int backlog)
{
    MY_ASSERT( 0 == listen(local_sfd, backlog), "listen failure!\n");
}

void my_accept(OUT int *peer_sfd, int local_sfd, OUT pSA peer_addr, IN_OUT int *addr_len )
{
    MY_ASSERT(-1 != (*peer_sfd = accept(local_sfd, peer_addr, addr_len)), "accept failure!\n");
}

/* client: connect */
void my_connect(int local_sfd, pSA peer_addr, int addr_len)
{
    int cnt = 0;
    // 10次连不上就退出程序
    while(-1 == connect(local_sfd, peer_addr, addr_len))
    {
        cnt++;
        if(cnt == 10)
        {
            printf("connect failure!\n");
            exit(EXIT_FAILURE);
        }
        sleep(1);
    }
}

/* recv and send */
void my_recv(OUT int *recv_len, int peer_sfd, IN_OUT void *base, int len)
{
    MY_ASSERT(-1 != (*recv_len = recv(peer_sfd, base, len, 0)), "recv error! \n");
}

void my_send(OUT int *send_len, int peer_sfd, void *base, int len)
{
    MY_ASSERT(-1 != (*send_len = send(peer_sfd, base, len, 0)), "send error! \n");
}

/*---------------------------- 以下针对UDP--------------------------------------------------------*/

void my_recvfrom(OUT int *recvfrom_len, int peer_sfd, IN_OUT void *base, int len, OUT pSA peer_addr, IN_OUT int *addr_len)
{
    MY_ASSERT(-1 != (*recvfrom_len = recvfrom(peer_sfd, base, len, 0, peer_addr, addr_len)), "recvfrom failure!\n");
}

void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  pSA peer_addr, int addr_len)
{
    MY_ASSERT(-1 != (*sendto_len = sendto(peer_sfd, base, len, 0, peer_addr, addr_len)), "sendto failure!\n");
}

/* close */
void my_close(int sfd)
{
    MY_ASSERT(0 == close(sfd), "close failure!\n");
}
编译成为动态库
gcc -fPIC -o my_socket.o -c my_socket.c
gcc -shared -o libmy_socket.so.1.0 my_socket.o

cp./libmy_socket.s0.3.1 /lib
cd /lib
ln -s libmy_socket.so.3.1 libmy_socket.so

//测试代码server.c
#include "my_socket.h"
#define IP "192.168.0.138"
#define PORT 8888
int main(int argc, char *argv[])
{
    int fd_server, fd_client;
    int val;  //用4个字节的地址空间来传数据
    int len;
    my_socket(&fd_server, MY_TCP, IP, PORT);
    my_listen(fd_server,5);
    my_accept(&fd_client, fd_server, NULL, NULL);
    printf("accept success!\n");
    while(1)
    {
        my_recv(&len, fd_client, (void*)&val, sizeof(val));
        printf("recv data: %d\n", val);
        my_send(&len, fd_client, (void*)&val, sizeof(val));
        printf("%d has sent!\n\n", val);
    }
    my_close(fd_client);
    my_close(fd_server);
    return 0;
}
//测试代码client.c
#include "my_socket.h"
#define IP "192.168.0.138"
#define MY_PORT 6666
#define SERVER_PORT 8888

int main(int argc, char *argv[])
{
    /* socket */
    int fd_client;
    my_socket(&fd_client, MY_TCP, IP, MY_PORT);

    /* connect */
    SA server_addr;
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(IP);

    my_connect(fd_client, (pSA)&server_addr, sizeof(SA));
    printf("connect success!\n");

    /* 发送一个数据,并从服务器端返回这个数据 */
    int val_in,val_out,len;
    while(scanf("%d", &val_in) == 1)
    {
        my_send(&len,fd_client,(void*)&val_in,sizeof(int));
        my_recv(&len,fd_client,(void*)&val_out,sizeof(int));
        printf("recv fron server: %d\n", val_out);
    }

    my_close(fd_client);
    return 0;

}//编译
gcc -o server server.c -lmy_socket -I ../includegcc -o client client.c -lmy_socket -I ../include
时间: 2024-10-21 14:35:51

将TCP 和UDP封装成动态库的相关文章

表格树控件QtTreePropertyBrowser编译成动态库(设计师插件)

目录 一.回顾 二.动态库编译 1.命令行编译动态库和测试程序 2.vs工具编译动态库和测试程序 3.安装文档 4.测试文档 三.设计师插件编译 1.重写QDesignerCustomWidgetInterface 2.添加到插件列表 3.拷贝生成的dll 4.重启Qt Designer 四.多说一句 五.相关文章 一.回顾 上一篇文章超级实用的表格树控件--QtTreePropertyBrowser讲了怎么去编译QtTreePropertyBrowser库,并且可以简单实用.由于我下载的库是基

将静态库制作成动态库

一.系统说明 Ubuntu12.04TLS 64位 二.制作静态库 (1)编写需要制作成静态库的程序(根据实际情况进行编写,这里只是一个简单例子)     //bar.h              #ifndef _BAR_H     #define _BAR_H          void bar(int i);          #endif     //bar.c     #include <stdio.h>     #include <stdlib.h>     #incl

Android导入第三方静态库.a编译成动态库.so

http://ikinglai.blog.51cto.com/6220785/1324985 在Android开发的时候,经常会使用到用c或c++编写的第三方的静态库.如果有源码的话,可以直接跟你自己的代码一去编译成动态库so,但是如果没有源码的话,你就必须在自己的动态库so里面将别人生成好的静态库导入进来一起编译了.我在编译的时候遇到了不少问题,我觉得有必要进行总结一下. 下面我以一个简单的实际例子来讲解如何在动态库中导入静态库. 静态库中的源代码有两个文件:static.h, static.

DPDK编译成动态库,应用程序检测不到端口的问题

把DPDK由静态库方式改为编译成动态库后,原本正常的应用程序就不能运行了. 在初始化的时候,rte_eth_dev_count()总是返回0,而用dpdk_nic_bind.py --status查看端口是绑定成功的. DPDK默认是编译成静态库的,改成动态库只需要把common_linuxapp文件中CONFIG_RTE_BUILD_SHARED_LIB=n修改成CONFIG_RTE_BUILD_SHARED_LIB=y就行了. DPDK编译成动态库后,PMD的各个驱动就单独编译成了一个个的.

cmake--生成--动态库

一, 目录结构 ├── CMakeLists.txt├── include│      └── shared│              └── Hello.h└── src         ├── Hello.cpp         └── main.cpp * link:CMakeLists.txt[] - Contains the CMake commands you wish to run * link:include/shared/Hello.h[] - The header file

C#对C++动态库的封装总结

我只是粗浅的学习过一些C++语法, 变量类型等基础内容, 如有不对的地方还望指出. 如果你跟我一样, 对指针操作不了解, 对封装C++动态库头疼的话, 下面内容还是有帮助的. 转载请注明出处: http://www.cnblogs.com/zaiyuzhong/p/Csharp-package-Cplusplus-dll.html 首先给一个类型转换的表, 这个表可能跟使用时具体情况有关, 仅供参考, 点击这里查看. 1. C++变量类型大小写问题: 一种是小写的, 比如char. 这种是系统定

Linux环境编译动态库和静态库总结

对Linux环境动态库和静态库的一些基础知识做一些总结, 首先总结静态库的编译步骤. 1 先基于.cpp或者.c文件生成对应的.o文件 2将几个.o文件 使用ar -cr命令 生成libname.a文件 libname.a 为静态库, name 为静态库的名字, 可以根据模块功能命名. 举个例子 在当前目录下,有一个mymethod.h文件 在mymethod.cpp里实现这两个函数 在当前目录下有一个main.cpp文件 为了方便使用,将mymethod.cpp封装成静态库和动态库 首先将my

face++静态库转为动态库

前言 苹果商店上架应用,有规定支持iOS8.0以上的iPA可执行文件的大小不能超过60M. face++提供过来的是静态库,会导致苹果上架的ipa的包增加1.5M左右.而刚好我们的APP包Mach-O文件大小接近60M,因而,最好的方式是通过动态库的方式来接入. Face++文件: https://faceid.com/pages/documents/37661898 SDK需要问Face++的人拿,Demo跑起来是需要key和secret的 静态库转动态库 静态库转动态库,有两种转换方式,一是

Linux动态库相关知识整理

动态库和静态库在C/C++开发中很常见,相比静态库直接被编译到可执行程序, 动态库运行时加载使得可执行程序的体积更小,更新动态库可以不用重新编译可执 行程序等诸多好处.作者是一个Linux后台开发,这些知识经常用到,所以 整理了一下这方面的知识.静态库相对简单,本文只关心Linux平台下的动态库. 创建动态库 这里我把一个短小却很有用的哈希函数编译成动态库做为示例,ELFhash用于对字符串做哈希,返回一个无符号整数. //elfhash.h #include <stdio.h> unsign