UNIX网络编程:如何使用select函数的TCP和UDP回射服务器程序

服务器程序:

#include <sys/wait.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#define SERV_PORT 3334
#define LISTENQ 5
#define MAXLINE 100  

void str_echo(int sockfd)
{
    ssize_t     n;
    char        buf[MAXLINE];  

again:
    while ( (n = read(sockfd, buf, MAXLINE)) > 0)
        write(sockfd, buf, n);  

    if (n < 0 && errno == EINTR)
        goto again;
    else if (n < 0)
        perror("read");
}  

void sig_chld(int signo)
{
    pid_t   pid;
    int     stat;  

    while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
        printf("child %d terminated\n", pid);
    return;
}
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);  

        /* 4create 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, (struct sockaddr *) &servaddr, sizeof(servaddr));  

    listen(listenfd, LISTENQ);  

        /* 4create 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, (struct sockaddr *) &servaddr, sizeof(servaddr));
    signal(SIGCHLD, sig_chld);  /* must call waitpid() */

    FD_ZERO(&rset);
    maxfdp1 =( (listenfd>udpfd)?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
                perror("select");
        }  

        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 */
        }  

        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);
        }
    }
}

57-67    创建一个监听TCP套接字并捆绑服务器的众所周知的端口,设置SO_REUSEADDR套接字选项以防止该端口上已有连接存在。

70-77     还创建一个UDP套接字并捆绑与TCP套接字相同的端口。这里无需在调用bind之前设置SO_REUSEADDR套接字选项,因为TCP端口是独立于UDP端口的。

78        给SIGCHLD建立信号处理程序,因为TCP连接将由某个子进程处理。

83-90     我们调用select只是为了等待监听TCP套接字的可读条件或UDP套接字的可读条件。既然我们的sig_chld信号处理函数可能中断我们对select的调用,于是我们需要处理EINTR错误。

作者:csdn博客 ctthuangcheng

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/unix/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索socket
, struct
, include
, sizeof
, 套接字
端口
,以便于您获取更多的相关知识。

时间: 2024-09-04 09:00:00

UNIX网络编程:如何使用select函数的TCP和UDP回射服务器程序的相关文章

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.15 使用select函数的TCP和UDP回射服务器程序

8.15 使用select函数的TCP和UDP回射服务器程序 现在,我们把第5章中的并发TCP回射服务器程序与本章中的迭代UDP回射服务器程序组合成单个使用select来复用TCP和UDP套接字的服务器程序.图8-24是该程序的前半部分. 创建监听TCP套接字14~22 创建一个监听TCP套接字并捆绑服务器的众所周知端口,设置SO_REUSEADDR套接字选项以防该端口上已有连接存在. 创建UDP套接字23~29 还创建一个UDP套接字并捆绑与TCP套接字相同的端口.这里无需在调用bind之前设

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.3 UDP回射服务器程序:main函数

8.3 UDP回射服务器程序:main函数 现在,我们用UDP重新编写第5章中简单的回射客户/服务器程序.我们的UDP客户程序和服务器程序依循图8-1中所示的函数调用流程.图8-2描述了它们所使用的函数,图8-3则给出了服务器程序的main函数. 创建UDP套接字,捆绑服务器的众所周知端口7~12 我们通过将socket函数的第二个参数指定为SOCK_DGRAM(IPv4协议中的数据报套接字)创建一个UDP套接字.正如TCP服务器程序的例子,用于bind的服务器IPv4地址被指定为INADDR_

UNIX网络编程:UDP回射服务器程序(初级版本)及漏洞分析

该函数提供的是一个迭代服务器,而不是像TCP服务器那样可以提供一个并发服务器.其中没有对fork的调用,因此单个服务器进程就得处理所有客户.一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是迭代的. 对于本套接字,UDP层中隐含有排队发生.事实上每个UDP套接字都有一个接收缓冲区,到达该套接字的每个数据报都进入这个套接字接收缓冲区.当进程调用recvfrom时,缓冲区中的下一个数据报以FIFO(先入先出)顺序返回给进程. 服务器程序: #include<stdio.h> #inclu

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.6 UDP回射客户程序:dg_cli函数

8.6 UDP回射客户程序:dg_cli函数 图8-8给出了dg_cli函数,它执行客户的大部分处理工作. 7~12 客户处理循环中有四个步骤:使用fgets从标准输入读入一个文本行,使用sendto将该文本行发送给服务器,使用recvfrom读回服务器的回射,使用fputs把回射的文本行显示到标准输出. 我们的客户尚未请求内核给它的套接字指派一个临时端口.(对于TCP客户而言,我们说过connect调用正是这种指派发生之处.)对于一个UDP套接字,如果其进程首次调用sendto时它没有绑定一个

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.5 UDP回射客户程序:main函数

8.5 UDP回射客户程序:main函数 图8-7给出了UDP客户程序的main函数. 把服务器地址填入套接字地址结构9~12 把服务器的IP地址和端口号填入一个IPv4的套接字地址结构.该结构将传递给dg_cli函数,以指明数据报将发往何处. 13~14 创建一个UDP套接字,然后调用dg_cli.

《UNIX网络编程 卷1:套接字联网API(第3版)》——导读

**前言**本书面向的读者是那些希望自己编写的程序能使用称为套接字(socket)的API进行彼此通信的人.有些读者可能已经非常熟悉套接字了,因为这个模型几乎已经成了网络编程的同义词,但有些读者可能仍需要从头开始学习.本书想达到的目标是向大家提供网络编程指导.这些内容不仅适用于专业人士,也适用于初学者:不仅适用于维护已有代码,也适用于开发新的网络应用程序:此外,还适用于那些只是想了解一下自己系统中网络组件的工作原理的人. 书中的所有示例都是在Unix系统上测试通过的真实的.可运行的代码.但是,考

《UNIX网络编程 卷1:套接字联网API(第3版)》——8.2 recvfrom和sendto函数

8.2 recvfrom和sendto函数 这两个函数类似于标准的read和write函数,不过需要三个额外的参数. #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen); ssize_t sendto(int sockfd, const void *buff, size_t nby

select-调试信息无法打印 unix网络编程

问题描述 调试信息无法打印 unix网络编程 如代码注释信息所示,应该是缓冲区的问题,但是stderr是无缓冲区的,而且也使用了fflush函数,也没用.希望能有人指点指点,谢谢 #include "globle.h" #define port 8082 int main( int argc, char *argv[] ){ fprintf(stderr, "11111111111n");//无法打印 fflush(stdout); int listenfd,soc

UNIX网络编程之旅-配置unp.h头文件环境

最近在学习Unix网络编程(UNP),书中steven在处理网络编程时只用了一个#include "unp.h"  相当有个性并且也很便捷 于是我把第三版的源代码编译实现了这个过程,算是一种个性化的开发环境的搭建吧,顺便把过程记录下来,以便自己以后查阅.   首先去网上找到源代码包unpv.13e.tar.gz 一找一大堆 解压缩到你的某个目录,unpv13e里面大致有这些目录 ├── aclocal.m4 ├── advio ├── bcast ├── config.guess ├─