同时使用tcp和udp回射服务器

来源:互联网 发布:淘宝直播买翡翠靠谱吗 编辑:程序博客网 时间:2024/05/15 05:39

同时使用select函数的tcp和udp回射服务器:

#include <iostream>#include <sys/socket.h>#include <sys/types.h>#include <strings.h>#include <arpa/inet.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/wait.h>using namespace std;#define MAXLINE     1024#define SERV_PORT   29988   //server使用的本地端口#define LISTENQ     100     //listen侦听队列最大数typedef struct sockaddr SA;void sig_chld(int signo) {    pid_t pid;    int stat;    //使用waitpid回收子进程    while((pid=waitpid(-1,&stat,WNOHANG))>0){        cout << "child " << pid << " terminated." << endl;    }    return ;}void str_echo(int sockfd) {    ssize_t n;    char buf[MAXLINE];    again:    while((n=read(sockfd,buf,MAXLINE))>0){        write(sockfd,buf,n);    }    //如果errno为EINTR,表示被信号中断的系统调用,可以重入,应该重新调用    if(n<0 && errno==EINTR){        goto again;    } else {        cout << "str_echo read error." << endl;        exit(-1);    }}int main(int argc , char** argv) {    int listenfd,connfd,udpfd,nready,maxfdp1;    char mesg[MAXLINE];    pid_t childpid;    fd_set rset;    ssize_t n;    socklen_t len;    const int on = 1;    struct sockaddr_in cliaddr,servaddr;    void sig_chld(int);    //创建TCP本地套接字,指定端口,地址任意选取本地接口    listenfd = socket(AF_INET,SOCK_STREAM,0);    bzero(&servaddr,sizeof(servaddr));    servaddr.sin_family=AF_INET;    servaddr.sin_addr.s_addr = htonl(0);    servaddr.sin_port=htons(SERV_PORT);    //设置套接字端口可以重入    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));    //绑定一个本地套接字地址    bind(listenfd,(SA*)&servaddr,sizeof(servaddr));    //侦听本地套接字,最大排队数量为LISTENQ    listen(listenfd,LISTENQ);    //创建本地UDP套接字    udpfd = socket(AF_INET,SOCK_DGRAM,0);    bzero(&servaddr,sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_addr.s_addr=htonl(0);    servaddr.sin_port = htons(SERV_PORT);    //绑定一个本地套接字地址    bind(udpfd,(SA*)&servaddr,sizeof(servaddr));    //注册信号SIGCHLD,回收fork子进程    signal(SIGCHLD,sig_chld);    FD_ZERO(&rset);    maxfdp1 = max(listenfd,udpfd) +1;    for(;;){        //添加侦听套接字listenfd和本地udp套接字到select可读集合        FD_SET(listenfd,&rset);        FD_SET(udpfd,&rset);        //使用select判断是否可以读        if((nready = select(maxfdp1,&rset,NULL,NULL,NULL)<0)){            if(errno == EINTR){                continue;            } else {                cout << "select error ." << endl;                exit(-1);            }        }        //检测listenfd        if(FD_ISSET(listenfd,&rset)){            len = sizeof(cliaddr);            connfd = accept(listenfd,(SA*)&cliaddr,&len);            //创建子进程,实现并发服务器            if((childpid=fork())==0){                close(listenfd);                str_echo(connfd);                exit(0);            }            close(connfd);        }        //检测udpfd        if(FD_ISSET(udpfd,&rset)){            len=sizeof(cliaddr);            n=recvfrom(udpfd,mesg,MAXLINE,0,(SA*)&cliaddr,&len);            sendto(udpfd,mesg,n,0,(SA*)&cliaddr,len);        }    }    return 0;}       
0 0
原创粉丝点击