《unix网络编程》(19)使用select的TCP和UDP回射程序

TCP和UDP服务器端程序

注意:信号处理函数可能中断对select的调用,因此要处理EINTR错误

//udpservselect01.c

#include "myheader.h"

void str_echo(int sockfd) {
   ssize_t n;
   char buf[MAXLINE];
again:
   while (( n = read(sockfd, buf, MAXLINE)) > 0)
      Writen(sockfd, buf, n);
   if (n < 0 && errno == EINTR)
      goto again;
   else if (n < 0) {
      err_exit("str_echo: read error.");   
   }
}

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 onSignalCatch(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);
  
  //设置SO_REUSEADDR套接字以防该端口上已经有连接
  Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  Bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
  Listen(listenfd, LISTENQ);
  
  //以下创建UDP套接字并绑定与TCP套接字相同的端口。这里无须设置SO_REUSEADDR
  //因为TCP端口独立于UDP端口
  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, (struct sockaddr*)&servaddr, sizeof(servaddr));
  
  //处理SIGCHLD信号,因为TCP连接由子进程处理
  Signal(SIGCHLD, onSignalCatch);
  
  FD_ZERO(&rset);
  //计算等待的描述符中较大的
  int maxfd = listenfd > udpfd ? listenfd : udpfd;
  maxfdp1 = maxfd + 1;
  
  for( ; ; ) {
    //调用select等待监听TCP或UDP套接字变为可读
    FD_SET(listenfd, &rset);
    FD_SET(udpfd, &rset);
    if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
      //信号处理函数可能中断对select的调用,因此要处理EINTR错误
      if (errno == EINTR)
	continue;
      else
	err_exit("select error\n");
    }
    
    if (FD_ISSET(udpfd, &rset)) {
      len = sizeof(cliaddr);
      n = Recvfrom(udpfd, mesg, MAXLINE, 0, (struct sockaddr*)&cliaddr, &len);
      Sendto(udpfd, mesg, n, 0, (struct sockaddr*)&cliaddr, len);
    }
    
    if (FD_ISSET(listenfd, &rset)) {
      len = sizeof(cliaddr);
      connfd = Accept(listenfd, (struct sockaddr*)&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
    }
  }
}
客户端程序分别使用:tcpcliselect.c 和udpcli01.c

程序运行结果

服务器端:tcp客户端进程中断了一次

tcp客户端:

udp客户端:


完整源码

http://download.csdn.net/download/u013074465/8602301

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值