- 论坛徽章:
- 0
|
原文出处http://www.xinxi888.com/Library/www/UNIX/UNIX17.HTM
感谢原作者的贡献
使用select 函数的TCP&UDP 回射服务器程序是并发TCP回射服务器程序与迭代UDP回射
服务器程序使用select复用组合为TCP和UDP套接口的单个服务器程序.
- // TCP并发服务器
- int main(int argc, char **argv)
- { int listenfd, connfd;
- pid_t childpid;
- socklen_t clilen;
- struct sockaddr_in cliaddr, servaddr;
- void sig-chld(int);
- listenfd = Socket(AF_INET, SOCK_STREAM, 0);
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
- Listen(listenfd, LISTENQ);
- Signal(SIGCHLD, sig_chld); /* must call waitpid() */
- for ( ; ; ) {
- clilen = sizeof(cliaddr);
- if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
- if (errno == EINTR)
- continue; /* back to for() */
- else
- err_sys("accept error");
- }
- if ( (childpid = Fork()) == 0) { /* child process */
- Close(listenfd); /* close listening socket */
- str_echo(connfd); /* process the request */
- exit(0);
- }
- Close(connfd); /* parent closes connected socket */
- }
- }
复制代码
- 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);
- /*create listening TCP socket */
- listenfd = Socket(AF_INET, SOCK_STREAM, 0);
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
- Listen(listenfd, LISTENQ);
- /*create UDP socket */
- udpfd = Socket(AF_INET, SOCK_DGRAM, 0);
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- Bind(udpfd, (SA *) &servaddr, sizeof(servaddr));
- Signal(SIGCHLD, sig_chld); /* must call waitpid() */
- FD_ZERO(&rset);
- maxfdp1 = max(listenfd, udpfd) + 1
- for ( ; ; ) {
- FD_SET(listenfd, &rset);
- FD_SET(udpfd, &rset);
- if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
- if (errno == EINTR) continue; /* back to for() */
- else err_sys("select error");
- }
- if (FD_ISSET(listenfd, &rset)) {
- len = sizeof(cliaddr);
- connfd = Accept(listenfd, (SA *) &cliaddr, &len);
- if ( (childpid = Fork()) == 0) { /* child process */
- Close(listenfd); /* close listening socket */
- str_echo(connfd); /* process the request */
- exit(0);
- }
- Close(connfd); /* parent closes connected socket */
- }
- 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);
- }
- }
- }
复制代码
定义变量
int listenfd : TCP监听套接口
int connfd: TCP已连接套接口,
int udpfd:UDP 套接口,
int nready:select函数中的准备好的描述字个数
int maxfdp1:select函数中的最大的描述字个数
char mesg[MAXLINE]:回射的字符串
pid_t childpid: TCP已连接套接口的进程编号
fd_set rset:select函数中的监听读描述字集
ssize_t n:回射的字符串的长度
socklen_t len:套接口地址长度
const int on = 1; 基本套接口选项SO_REUSEADDR的参数
SA cliaddr, servaddr :服务器客户套接口地址结构
void sig_chld(int);信号处理函数
创建TCP监听套接口
listenfd = Socket(AF_INET, SOCK_STREAM, 0); //建立TCP套接口描述字
bzero(&servaddr, sizeof(servaddr)); //地址结构清零
servaddr.sin_family = AF_INET; //IPv4协议
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //内核指定地址
servaddr.sin_port = htons(SERV_PORT); //总所诸知端口#9877
// 允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用作它们的本地端口的连接仍存在。
Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); //绑定本机地址和端口
Listen(listenfd, LISTENQ); //监听
创建UPD套接口
udpfd = Socket(AF_INET, SOCK_DGRAM, 0); //建立UDP套接口描述字
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(udpfd, (SA *) &servaddr, sizeof(servaddr)); //绑定本机地址和端口
|
|