[百晓生]-linux网络多路复用IO技术

 
[百晓生]-linux网络多路复用IO技术
 
1.mystery引入
    1)Select是一种多路复用IO输入输出模式,在linux的输入输出编程中通过select的轮询机制,发现可用/可读或可写的接口。
    2)低级socket程序中有一个共同点:都是基于阻塞式的编程方式
    3)非阻塞式是函数调用时不阻塞,不管函数执行成功与否,都会立即返回。
    4)优点:程序效率提升
    5)缺点:返回的结果往往是错误的类型码
    6)解决方案:Select机制。

2.实例操作
    1)基于Select模式实现一个网络echo的服务程序,即客户端向服务端发送信息,服务器接收到信息后,再将信息原样转发给客户端
    2)需要设置Select函数
    3)若当前有新连接,则加入到客户端套接字集合,若数量过载,则断开本次连接,并发送提示信息:sorry overload
    4)源代码
 
//selectsocket.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define SERVER_PORT 5555    
#define QUEUE_LENGTH 5     
#define BUF_SIZE 200
 
int main(void)
{
    int server_socket, new_socket;  
    struct sockaddr_in server_addr;    
    struct sockaddr_in client_addr; 
    socklen_t sin_size;
int client_socket[QUEUE_LENGTH];    
int conn_num;    
    int yes = 1;
    char buf[BUF_SIZE];
    int ret;
    int i;
 
    if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
{
        perror("socket");
        return 0;
     }
 
    if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
        perror("setsockopt");
        return 0;
     }
    
    server_addr.sin_family = AF_INET;         
    server_addr.sin_port = htons(SERVER_PORT);     
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
 
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) 
{
        perror("bind");
        return 0;
     }
 
    if (listen(server_socket, 5) == -1) 
    {
        perror("listen");
        return 0;
    }
 
    printf("listen port %d\n", SERVER_PORT);
 
    fd_set clientfdset;
    int maxsock;
    struct timeval tv;
 
    conn_num = 0;
    sin_size = sizeof(client_addr);
    maxsock = server_socket;
    while (1)
{
        // initialize file descriptor set
        FD_ZERO(&clientfdset);
        FD_SET(server_socket, &clientfdset);
 
        // timeout setting
        tv.tv_sec = 15;
        tv.tv_usec = 0;
 
        // add active connection to fd set
        for (i = 0; i < QUEUE_LENGTH; i++) 
{
            if (client_socket[i] != 0) 
{
                FD_SET(client_socket[i], &clientfdset);
             }
        }
 
        ret = select(maxsock + 1, &clientfdset, NULL, NULL, &tv);
        if (ret < 0)
    {
            perror("select");
            break;
            }
else if (ret == 0)
{
    printf("waitting timeout\n");
    continue;
         }
 
        // check every fd in the set
        for (i = 0; i < conn_num; i++) 
{
             if (FD_ISSET(client_socket[i], &clientfdset)) 
{
ret = recv(client_socket[i], buf, sizeof(buf), 0);
if (ret <= 0) 
{        
    printf("client[%d] close\n", i);
    close(client_socket[i]);
    FD_CLR(client_socket[i], &clientfdset);
    client_socket[i] = 0;
                 } 
else
{     
                     printf("Client[%d] msg:%s\n", i, buf);
send(client_socket[i], buf, sizeof(buf), 0);
                 }
             }
         }
 
        if (FD_ISSET(server_socket, &clientfdset)) 
    {
            new_socket = accept(server_socket, (struct sockaddr *)&client_addr, &sin_size);
            if (new_socket <= 0)
{
perror("accept");
continue;
             }
 
            if (conn_num < QUEUE_LENGTH)
{
client_socket[conn_num++] = new_socket;
printf("new client[%d] %s:%d\n", conn_num,
        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (new_socket > maxsock)
    maxsock = new_socket;
             }
            else 
{
send(new_socket, "sorry overload!", sizeof("sorry overload!"), 0);
close(new_socket);
break;
             }
          }
    }
 
    
    for (i = 0; i < QUEUE_LENGTH; i++) 
{
        if (client_socket[i] != 0) 
{
             close(client_socket[i]);
         }
     }
 
}

3.mystery注解
    1)设置高级socket属性参数中的应用参数SO_REUSERADDR,实现地址的可重复利用
    2)FD_SET(int fd, fd_set *fdset):向文件描述符集合中增加一个新的文件描述符
    3)FD_CLR(int fd, fd_set *fdset):向文件描述符集合中删除一个文件描述符
 
 
 

你可能感兴趣的:(linux,源代码,服务器,解决方案,多路复用,提示信息,百晓生,IO技术,网络多路复用)