Linux网络编程9——对TCP与UDP的简易封装2.0

具体生成动态库的操作及使用该动态库的操作请参见上篇博文。以下仅仅列出改进版本的代码。

代码

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, char *peer_ip, int peer_port);

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 char* peer_ip, OUT int *peer_port);

void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  char *peer_ip, int peer_port);

void my_close(int sfd);





#endif

my_socket.c

/*************************************************************************

    > File Name: my_socket.c

    > Author: KrisChou

    > Mail:[email protected] 

    > Created Time: Mon 01 Sep 2014 06:54:48 PM CST

 ************************************************************************/



/* 本代码用于在一台主机上模拟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");

        int reuse = 1;

        setsockopt(*local_sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse));

    }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, char *peer_ip, int peer_port )

{

    int cnt = 0;

    SA peer_addr;

    memset(&peer_addr, 0, sizeof(SA));

    peer_addr.sin_family      = AF_INET;

    peer_addr.sin_port        = htons(peer_port);

    peer_addr.sin_addr.s_addr = inet_addr(peer_ip);

    // 10次连不上就退出程序

    while(-1 == connect(local_sfd, (pSA)&peer_addr, sizeof(SA)))

    {

        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)

{

    int recvn;

    int recv_sum = 0;

    while(recv_sum < len)

    {

        MY_ASSERT(-1 != (recvn = recv(peer_sfd, base + recv_sum, len - recv_sum, 0)), "recv error! \n");

        recv_sum += recvn;

    }

    if(recv_len != NULL)

    {

        *recv_len = recv_sum;

    }

}



void my_send(OUT int *send_len, int peer_sfd, void *base, int len)

{

    int sendn;

    int send_sum = 0;

    while(send_sum < len)

    {

        MY_ASSERT(-1 != (sendn = send(peer_sfd, base + send_sum, len - send_sum, 0)), "send error! \n");

        send_sum += sendn;

    }

    if(send_len != NULL)

    {

        *send_len = send_sum;

    }

}



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



void my_recvfrom(OUT int *recvfrom_len, int peer_sfd, IN_OUT void *base, int len, OUT char* peer_ip, OUT int *peer_port)

{

    int recvn;

    SA peer_addr;

    int addr_len = sizeof(SA);

    MY_ASSERT(-1 != (recvn = recvfrom(peer_sfd, base, len, 0, (pSA)&peer_addr, &addr_len)), "recvfrom failure!\n");

    if(recvfrom_len != NULL)

    {

        *recvfrom_len = recvn;

    }

    if(peer_ip != NULL)

    {

        char *p = inet_ntoa(peer_addr.sin_addr);

        MY_ASSERT(strlen(peer_ip) >= strlen(p) + 1, "buf for ip is too short! \n");

        strcpy(peer_ip, p);

    }

    if(peer_port != NULL)

    {

        *peer_port = ntohs(peer_addr.sin_port);

    }

}





void my_sendto(OUT int *sendto_len, int peer_sfd, OUT void *base, int len,  char *peer_ip, int peer_port)

{

    int sendn;

    SA peer_addr;

    memset(&peer_addr, 0, sizeof(SA));

    peer_addr.sin_family      = AF_INET;

    peer_addr.sin_port        = htons(peer_port);

    peer_addr.sin_addr.s_addr = inet_addr(peer_ip);

    MY_ASSERT(-1 != (sendn = sendto(peer_sfd, base, len, 0, (pSA)&peer_addr, sizeof(SA))), "sendto failure!\n");

    if(sendto_len != NULL)

    {

        *sendto_len = sendn;

    }

}







/* close */

void my_close(int sfd)

{

    MY_ASSERT(0 == close(sfd), "close failure!\n");

}

测试代码

server.c

#include "my_socket.h"

#define IP "192.168.153.128"

#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_accept(&fd_client, fd_server, NULL, NULL);

        //printf("accept success!\n");

        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.153.128"

#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 */

    my_connect(fd_client, IP, SERVER_PORT);

    printf("connect success!\n");

    

    /* 发送一个数据,并从服务器端返回这个数据 */

    int val_in,val_out,len;

    while(scanf("%d", &val_in) == 1)

    {

        my_send(NULL,fd_client,(void*)&val_in,sizeof(int));

        my_recv(NULL,fd_client,(void*)&val_out,sizeof(int));

        printf("recv fron server: %d\n", val_out);

    }

    

    my_close(fd_client);

    return 0;

    

}

你可能感兴趣的:(linux)