网络程序设计——5.I/O复用完成单线程并发服务器的处理

一、实验要求

    在前期ECHO代码的基础上,利用I/O复用完成单线程并发服务器的实现。

二、实验分析

    使用select实现单线程ECHO服务器:

  • 在熟知端口上打开一个被动套接字
  • 使用系统函数getdtablesize来决定描述符最大个数
  • 使用FD_ZERO和FD_SET创建一个比特向量,对应于希望测试的套接字描述符
  • select等待一个或者多个描述符就绪 FD_ISSET测试哪个描述符就绪
  • FD_CLR关闭连接后,从描述符组中删除

三、实验内容

    1.tcp_server.c

#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>  /*for errno*/
#define BUFFER_SIZE 1024
#define QLEN        32

int process_conn_server(int fd);

int main(int argc, char *argv[])
{
    char *service = "echo";
    struct sockaddr_in fsin;
    int msock;
    fd_set rfds;    //лв╫свжап╠М
    fd_set afds;
    int alen;
    int fd, nfds;

    switch(argc)
    {
    case 1:
        break;
    case 2:
        service = argv[1];
        break;
    default:
        errexit("usage: TCPmechod [PORT]\n");
    }

    msock = passiveTCP(service, QLEN);

    nfds = getdtablesize();
    FD_ZERO(&afds);
    FD_SET(msock, &afds);
    int count = 0;
    while(1)
    {
        memcpy(&rfds, &afds, sizeof(rfds));
        if(select(nfds, &rfds, (fd_set*)0, (fd_set*)0, (struct timeval *)0) < 0)
            errexit("select: %s\n", strerror(errno));

        if(FD_ISSET(msock, &rfds)){
            int ssock;

            alen = sizeof(fsin);
            ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
            if(ssock < 0)
                errexit("accept: %s\n", strerror(errno));
            FD_SET(ssock, &afds);
        }
        for(fd = 0; fd < nfds; fd++)
        {

            if(fd != msock && FD_ISSET(fd, &rfds)){
                if(process_conn_server(fd) == 0){
                    (void) close(fd);
                    FD_CLR(fd, &afds);
                }
            }
        }
    }
}
int process_conn_server(int fd)
{
    char buf[BUFFER_SIZE];
    int cc;

    cc = read(fd, buf, sizeof(buf));
    if(cc < 0)
        errexit("echo read: %s\n", strerror(errno));
    if(cc == 0)
        return cc;
    printf("server read: %s size:%d\n", buf, strlen(buf));
    if(cc && write(fd, buf , cc) < 0)
        errexit("echo write: %s\n", strerror(errno));

    return cc;
}

    2.tcp_client.c

//tcp_client.c
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>  /*for errno*/
#define BUFFER_SIZE 1024

int process_conn_client(int socket);

int main(int argc, char * argv[])
{
    char *host = "localhost";
    char *service = "echo";
    switch(argc)
    {
    case 1:
        break;
    case 3:
        service = argv[2];
    case 2:
        host = argv[1];
        break;
    default:
        fprintf(stderr, "usage: TCPfiletransfer [ host [port]]\n");
        exit(1);
    }
    int socket = connectTCP(host, service);
    process_conn_client(socket);
    close(socket);
}
int process_conn_client(int socket)
{
    char buf[BUFFER_SIZE];
    int cc;

    scanf("%s", buf);                 /*不能读空格*/
//    cc = read(0, buf, BUFFER_SIZE);     /*能读出空格,但会读取回车*/
    cc = write(socket, buf, sizeof(buf));
    if(cc < 0)
        errexit("client write: %s\n", strerror(errno));
    if(cc && read(socket, buf, cc) < 0)
        errexit("client read: %s\n", strerror(errno));
    printf("client read: %s\n",buf);

    return cc;
}

    运行结果如下:

服务器:

客户端:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值