大家好,我是LinuxZn。
之前我们的文章中也有分享TCP相关的过程,一个TCP通信的框图如下:
这个图中也列出了常用的几个接口函数,其中,有几个函数调用时传参比较繁琐,为了提高我们的编码效率,有必要对这些接口的使用进一步地封装,使得函数调用更简单些。
TCP常用接口使用封装 下面给大家整理一份:
tcp_socket.h:
#ifndef TCP_SCOKET_H #define TCP_SCOKET_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <signal.h> #define MAX_CONNECT_NUM 10 int tcp_init (const char * ip, int port) ;int tcp_accept (int sfd) ;int tcp_connect (const char * ip, int port) ;int tcp_nonblocking_recv (int conn_sockfd, void *rx_buf, int buf_len, int timeval_sec, int timeval_usec) ;int tcp_blocking_recv (int conn_sockfd, void *rx_buf, uint16_t buf_len) ;int tcp_send (int conn_sockfd, uint8_t *tx_buf, uint16_t buf_len) ;void tcp_close (int sockfd) ;#endif
tcp_socket.c:
#include 'tcp_socket.h' int tcp_init (const char * ip, int port) { int optval = 1 ; int server_fd = socket(AF_INET, SOCK_STREAM, 0 ); if (server_fd < 0 ) { perror('socket' ); return -1 ; } /* 解除端口占用 */ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) < 0 ) { perror('setsockopt\n' ); return -1 ; } struct sockaddr_in server_addr ; bzero(&server_addr, sizeof (struct sockaddr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); if (NULL == ip) { server_addr.sin_addr.s_addr = htonl(INADDR_ANY); } else { server_addr.sin_addr.s_addr = inet_addr(ip); } if (bind(server_fd, (struct sockaddr*)&server_addr,sizeof (struct sockaddr)) < 0 ) { perror('bind' ); close(server_fd); return -1 ; } if (listen(server_fd, MAX_CONNECT_NUM) < 0 ) { perror('listen' ); close(server_fd); return -1 ; } return server_fd; }int tcp_accept (int server_fd) { struct sockaddr_in client_addr = {0 }; int addrlen = sizeof (struct sockaddr); int new_fd = accept(server_fd, (struct sockaddr*) &client_addr, &addrlen); if (new_fd < 0 ) { perror('accept' ); close(server_fd); return -1 ; } return new_fd; }int tcp_connect (const char *ip, int port) { int server_fd = socket(AF_INET, SOCK_STREAM, 0 ); if (server_fd < 0 ) { perror('socket' ); return -1 ; } struct sockaddr_in server_addr ; bzero(&server_addr, sizeof (struct sockaddr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr(ip); if (connect(server_fd, (struct sockaddr*)&server_addr, sizeof (struct sockaddr)) < 0 ) { perror('connect' ); close(server_fd); return -1 ; } return server_fd; }int tcp_nonblocking_recv (int conn_sockfd, void *rx_buf, int buf_len, int timeval_sec, int timeval_usec) { fd_set readset; struct timeval timeout = {0 , 0 }; int maxfd = 0 ; int fp0 = 0 ; int recv_bytes = 0 ; int ret = 0 ; timeout.tv_sec = timeval_sec; timeout.tv_usec = timeval_usec; FD_ZERO(&readset); FD_SET(conn_sockfd, &readset); maxfd = conn_sockfd > fp0 ? (conn_sockfd+1 ) : (fp0+1 ); ret = select(maxfd, &readset, NULL , NULL , &timeout); if (ret > 0 ) { if (FD_ISSET(conn_sockfd, &readset)) { if ((recv_bytes = recv(conn_sockfd, rx_buf, buf_len, MSG_DONTWAIT))== -1 ) { perror('recv' ); return -1 ; } } } else { return -1 ; } return recv_bytes; }int tcp_blocking_recv (int conn_sockfd, void *rx_buf, uint16_t buf_len) { return recv(conn_sockfd, rx_buf, buf_len, 0 ); }int tcp_send (int conn_sockfd, uint8_t *tx_buf, uint16_t buf_len) { return send(conn_sockfd, tx_buf, buf_len, 0 ); }void tcp_close (int sockfd) { close(sockfd); }
测试代码 tcp_server.c:
#include 'tcp_socket.h' int main (int argc, char **argv) { printf ('==================tcp server==================\n' ); int server_fd = tcp_init(NULL , 4321 ); if (server_fd < 0 ) { printf ('tcp_init error!\n' ); exit (EXIT_FAILURE); } int client_fd = tcp_accept(server_fd); if (client_fd < 0 ) { printf ('tcp_accept error!\n' ); exit (EXIT_FAILURE); } while (1 ) { char buf[128 ] = {0 }; int recv_len = tcp_blocking_recv(client_fd, buf, sizeof (buf)); if (recv_len <= 0 ) { printf ('recv error!\n' ); tcp_close(client_fd); tcp_close(server_fd); exit (EXIT_FAILURE); } printf ('recv : %s\n' , buf); int send_len = tcp_send(client_fd, buf, strlen (buf)); if (send_len <= 0 ) { printf ('send error!\n' ); tcp_close(client_fd); tcp_close(server_fd); exit (EXIT_FAILURE); } else { printf ('send success! send: %s, send_len: %d\n' , buf, send_len); } } tcp_close(server_fd); return 0 ; }
tcp_client.c:
#include 'tcp_socket.h' int main (int argc, char **argv) { printf ('==================tcp cient==================\n' ); if (argc < 3 ) { printf ('usage:./tcp_client ip port\n' ); exit (EXIT_FAILURE); } char ip_buf[32 ] = {0 }; int port = 0 ; memcpy (ip_buf, argv[1 ], strlen (argv[1 ])); port = atoi(argv[2 ]); int server_fd = tcp_connect(ip_buf, port); if (server_fd < 0 ) { printf ('tcp_connect error!\n' ); exit (EXIT_FAILURE); } while (1 ) { char buf[128 ] = {0 }; if (scanf ('%s' , buf)) { int send_len = tcp_send(server_fd, buf, strlen (buf)); if (send_len <= 0 ) { printf ('tcp_send error!\n' ); tcp_close(server_fd); exit (EXIT_FAILURE); } else { printf ('send success! send: %s, send_len: %d\n' , buf, send_len); } bzero(buf, sizeof (buf)); int recv_len = tcp_blocking_recv(server_fd, buf, sizeof (buf)); if (recv_len <= 0 ) { printf ('tcp_blocking_recv error!\n' ); tcp_close(server_fd); exit (EXIT_FAILURE); } printf ('recv : %s\n' , buf); } } return 0 ; }
测试结果:
如果大家觉得文章不错,麻烦帮忙转发,谢谢!