用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

芙蓉妹妹    -  云代码空间

——

利用I/O复用完成单线程并发服务器的实现

2018-11-12|1348阅||

摘要:1)创建套接字并将其绑定到这个服务的熟知端口上,将该套接字加到一个表中,该表中的项是可以进行I/O的描述符。 2)使用select在已经有的套接字上等待I/O。 3)如果最初的套接字准备就绪,使用accept获得下一个连接,并将这个新的套接字加入到表中,该表中的项是可以进行I

一、服务器代码

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/time.h>

#include <netinet/in.h>

#include <unistd.h>

#include <string.h>

#include <stdio.h>

#include <errno.h>

#include <stdlib.h>

 

#define PORT 8888

#define LISTENQ 20

//#define BUFFSIZE 4096

#define FILE_NAME_MAX_SIZE 512

 

int echo(int sc){

     //process_conn_server(sc);       /*处理连接*/

      ssize_t size = 0;

      char buffer[1024];              /*数据的缓冲区*/  

      bzero(buffer,1024);

      size = read(sc, buffer, 1024);  /*从套接字中读取数据放到缓冲buffer*/

      printf("messages received from the client:");

      printf("%s",buffer);

      write(sc, buffer, size);/*发给客户端*/

      return size;

}

 

int passiveTCP (const char*service){

    //Create socket

    int sockfd,connfd;

    struct sockaddr_in svraddr,clientaddr;

    bzero(&svraddr,sizeof(svraddr));

 

    svraddr.sin_family=AF_INET;

    svraddr.sin_addr.s_addr=htonl(INADDR_ANY);

    svraddr.sin_port=htons(PORT);

 

    sockfd=socket(AF_INET,SOCK_STREAM,0);

    if(sockfd<0)

    {

        perror("socket");

        exit(1);

    }

 

    //bind  

    if(bind(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr))<0)

    {

        perror("bind");

        exit(1);

    }

 

    //listen

    if(listen(sockfd,LISTENQ)<0)

    {

        perror("listen");

        exit(1);

    }

    return sockfd;

}

 

int main(int argc, char *argv[])

{         

    char    *service = "echo";/* service name or port number*/

    struct sockaddr_in fsin;    /* the from address of a client */

    int msock;      /* master server socket     */

    fd_set  rfds;           /* read file descriptor set */

    fd_set  afds;           /* active file descriptor set   */

    unsigned int    alen;      /* from-address length   */

    int fd, nfds;

 

    msock = passiveTCP(service);

    nfds = getdtablesize();

    FD_ZERO(&afds);//将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的

    FD_SET(msock, &afds);//用于在文件描述符集合中增加一个新的文件描述符

    while (1) {

      memcpy(&rfds, &afds, sizeof(rfds));

      if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0,(struct timeval *)0) < 0)

        printf("select error");

      if (FD_ISSET(msock, &rfds)) {//用于测试指定的文件描述符是否在该集合中

        int ssock;

        alen = sizeof(fsin);

        ssock = accept(msock, (struct sockaddr *)&fsin,&alen);

        if (ssock < 0)

        printf("accept error");

 

        FD_SET(ssock, &afds);

        }

    for (fd=0; fd<nfds; ++fd)

        if (fd != msock && FD_ISSET(fd, &rfds))

            if (echo(fd) == 0) {

                close(fd);

                FD_CLR(fd, &afds);//用于在文件描述符集合中删除一个文件描述符

            }

  }

}

二、客户端代码

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <arpa/inet.h>

#define PORT 8888                               /*侦听端口地址*/

#define IP "192.168.91.128"                     /*服务器IP地址*/

 

int main(int argc, char *argv[])

{

    int s;                                      /*ssocket描述符*/

    struct sockaddr_in server_addr;             /*服务器地址结构*/

    s = socket(AF_INET, SOCK_STREAM, 0);        /*建立一个流式套接字 */

    if(s < 0){                                  /*出错*/

        printf("socket error\n");

        return -1;

    }

 

    /*设置服务器地址*/

    bzero(&server_addr, sizeof(server_addr));       /*清零*/

    server_addr.sin_family = AF_INET;               /*协议族*/

    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);/*本地地址*/

    server_addr.sin_port = htons(PORT);             /*服务器端口*/

 

    /*将用户的字符串类型的IP地址转为整型*/

    inet_pton(AF_INET, IP, &server_addr.sin_addr);

    /*连接服务器*/

    connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));

 

    ssize_t size = 0;

    char buffer[1024];                          /*数据的缓冲区*/

    for(;;){                                    /*循环处理过程*/

        bzero(buffer,1024);

        size = read(0, buffer, 1024);/*从标准输入中读取数据放到缓冲区buffer*/

        if(size > 0){                           /*读到数据*/

            write(s, buffer, size);             /*发送给服务器*/

            size = read(s, buffer, 1024);       /*从服务器读取数据*/

            printf("messages received from the server:");

            printf("%s",buffer);

        }

    }

    close(s);                                   /*关闭连接*/

    return 0;

}

三、实验结果
1、服务端

2、客户端(同时开三个客户端)

顶 2踩 2收藏
文章评论
    发表评论

    个人资料

    • 昵称: 芙蓉妹妹
    • 等级: 资深程序员
    • 积分: 1710
    • 代码: 104 个
    • 文章: 25 篇
    • 随想: 0 条
    • 访问: 32 次
    • 关注

    标签

    最新提问

      站长推荐