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:zhoujx0219@163.com > 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; }