1. 程式人生 > >同時使用tcp和udp回射伺服器

同時使用tcp和udp回射伺服器

同時使用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; }