zoukankan      html  css  js  c++  java
  • 将TCP封装成动态库

    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! 
    ");
        /* 创建本地socket */
        if(protocal == MY_TCP)
        {
            MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_STREAM, 0)), "tcp_socket init falure!
    ");
        }else if(protocal == MY_UDP)
        {
            MY_ASSERT(-1 != (*local_sfd = socket(AF_INET, SOCK_DGRAM, 0)),  "udp_socket init failure!
    ");
        }
        /* 将本地联系方式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!
    ");
    }
    
    /*----------------------------- 以下针对TCP ----------------------------------------------------- */
    
    /* server: listen + accept */
    void my_listen(int local_sfd, int backlog)
    {
        MY_ASSERT( 0 == listen(local_sfd, backlog), "listen failure!
    ");
    }
    
    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!
    ");
    }
    
    /* 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!
    ");
                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! 
    ");
    }
    
    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! 
    ");
    }
    
    /*---------------------------- 以下针对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!
    ");
    }
    
    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!
    ");
    }
    
    
    
    /* close */
    void my_close(int sfd)
    {
        MY_ASSERT(0 == close(sfd), "close failure!
    ");
    }

    编译成为动态库
    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!
    ");
        while(1)
        {
            my_recv(&len, fd_client, (void*)&val, sizeof(val));
            printf("recv data: %d
    ", val);
            my_send(&len, fd_client, (void*)&val, sizeof(val));
            printf("%d has sent!
    
    ", 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!
    ");
        
        /* 发送一个数据,并从服务器端返回这个数据 */
        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
    ", val_out);
        }
        
        my_close(fd_client);
        return 0;
        
    }
    //编译
    gcc -o server server.c -lmy_socket -I ../include
    gcc -o client client.c -lmy_socket -I ../include


  • 相关阅读:
    陈应松《母亲》
    黄灯:一个农村儿媳眼中的乡村图景
    喝完茶为什么嘴里是甜的
    俗语一千条
    XtraBackup完整备份与增量备份的原理
    李嘉诚:90%考虑失败 关注细节
    redo和undo的区别
    tar命令
    自增锁引发的悲剧
    各版本 MySQL 并行复制的实现及优缺点
  • 原文地址:https://www.cnblogs.com/hxjbc/p/3953014.html
Copyright © 2011-2022 走看看