一个socket只能与一个socket地址绑定即一个socket只能监听一个端口,服务器如果要同时监听多个端口就必须创建多个socket,若在同一个端口监听多个服务也要创建多个socket绑定到这个端口上。现在服务器监听一个端口上的TCP和UDP请求,并将发送来的数据回射到客户端。
服务端程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/epoll.h> #include <pthread.h> #define MAX_EVENT_NUMBER 1024 //最大事件数目 #define TCP_BUFFER_SIZE 512//TCP缓冲区 #define UDP_BUFFER_SIZE 1024//UDP缓冲区 int setnonblocking( int fd )//设置为非阻塞描述符 { int old_option = fcntl( fd, F_GETFL ); int new_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option; } void addfd( int epollfd, int fd )//注册事件 { epoll_event event; event.data.fd = fd; //event.events = EPOLLIN | EPOLLET; event.events = EPOLLIN;//可读事件 epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd ); } int main( int argc, char* argv[] ) { if( argc <= 2 ) { printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); int ret = 0; struct sockaddr_in address;//绑定TCP端口 bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); bzero( &address, sizeof( address ) );//绑定UDP端口 address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int udpfd = socket( PF_INET, SOCK_DGRAM, 0 ); assert( udpfd >= 0 ); ret = bind( udpfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); epoll_event events[ MAX_EVENT_NUMBER ]; int epollfd = epoll_create( 5 ); assert( epollfd != -1 ); addfd( epollfd, listenfd );//TCP端口注册事件 addfd( epollfd, udpfd );//UDP端口注册事件 while( 1 ) { int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );//无限期等待事件发生 if ( number < 0 ) { printf( "epoll failure\n" ); break; } for ( int i = 0; i < number; i++ )//EPOLL就绪事件 { int sockfd = events[i].data.fd; if ( sockfd == listenfd )//监听端口监听TCP连接事件 { struct sockaddr_in client_address; socklen_t client_addrlength = sizeof( client_address ); int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength ); addfd( epollfd, connfd ); } else if ( sockfd == udpfd )//UDP连接 { char buf[ UDP_BUFFER_SIZE ]; memset( buf, '\0', UDP_BUFFER_SIZE ); struct sockaddr_in client_address; socklen_t client_addrlength = sizeof( client_address );//客户端地址 //UDP专用接收数据 ret = recvfrom( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( struct sockaddr* )&client_address, &client_addrlength ); if( ret > 0 ) {//UDP专用发送数据(回射数据) sendto( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( struct sockaddr* )&client_address, client_addrlength ); } } else if ( events[i].events & EPOLLIN )//TCP连接 { char buf[ TCP_BUFFER_SIZE ]; while( 1 ) { memset( buf, '\0', TCP_BUFFER_SIZE ); ret = recv( sockfd, buf, TCP_BUFFER_SIZE-1, 0 ); if( ret < 0 ) { if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )//非阻塞出现这种errrno是读取数据完毕 { break; } close( sockfd ); break; } else if( ret == 0 )//关闭连接 { close( sockfd ); } else { send( sockfd, buf, ret, 0 );//回射数据 } } } else { printf( "something else happened \n" ); } } } close( listenfd ); return 0; } |
客户端程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<assert.h> #include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<iostream> #define BUF_SIZE 1024 using namespace std; int main(int argc,char* argv[]){ if(argc<=2){ cout<<"argc<=2"<<endl; return 1; } const char* ip=argv[1]; int port=atoi(argv[2]); struct sockaddr_in server_address; bzero(&server_address,sizeof(server_address)); server_address.sin_family=AF_INET; inet_pton(AF_INET,ip,&server_address.sin_addr); server_address.sin_port=htons(port); int sockfd=socket(PF_INET,SOCK_STREAM,0); int sockudp=socket(PF_INET,SOCK_DGRAM,0); assert(sockfd>=0); if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0){//TCP数据发送与接收 cout<<"connect error"<<endl; return 1; } else{ const char* tcp="this is TCP data\n"; send(sockfd,tcp,strlen(tcp),0); char buf[BUF_SIZE]; int ret=recv(sockfd,buf,BUF_SIZE-1,0); if(ret<0){ cout<<"recv tcp error"<<endl; } else{ buf[ret+1]='\0'; cout<<ret<<" "<<buf<<endl; } } if(connect(sockudp,(struct sockaddr*)&server_address,sizeof(server_address))<0){//UDP数据发送与接收 cout<<"connect error"<<endl; return 1; } else{ const char* udp="this is UDP data\n"; send(sockudp,udp,strlen(udp),0); char buf[BUF_SIZE]; int ret=recv(sockudp,buf,BUF_SIZE-1,0); if(ret<0){ cout<<"recv udp error"<<endl; } else{ buf[ret+1]='\0'; cout<<ret<<" "<<buf<<endl; } } close(sockfd); return 0; } |
爱你不是两三天,每月看你很多遍。