Linux網絡編程

TCP

service.c
服務端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(void)
{
    int sfp,nfp;
    struct sockaddr_in s_add,c_add;
    int sin_size;
    unsigned short portnum=0x8888;
    char buff[100]={0};

    printf("Hello,welcome to my server !\r\n");
    sfp = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sfp)
    {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");

    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr=htonl(INADDR_ANY);
    s_add.sin_port=htons(portnum);

    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("bind fail !\r\n");
        return -1;
    }
    printf("bind ok !\r\n");

    if(-1 == listen(sfp,5))
    {
        printf("listen fail !\r\n");
        return -1;
    }
    printf("listen ok\r\n");
    while(1)
    {
        sin_size = sizeof(struct sockaddr_in);

        nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
        if(-1 == nfp)
        {
            printf("accept fail !\r\n");
            return -1;
        }
        read(nfp,buff,100);
        printf("received:%s\n", buff);

        if(-1 == write(nfp,buff,strlen(buff)+1))
        {
            printf("write fail!\r\n");
            return -1;
        }
        printf("write ok!\r\n");
        close(nfp);
    }
    close(sfp);
    return 0;
}

makefile:

server:server.o
    gcc -o server server.o
server.o:server.c
    gcc -c server.c -o server.o
clean:
    rm -f *.o server

=====================
客戶端
client.c

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(void)
{
    int cfd;
    int recbytes;
    int sin_size;
    char buffer[1024]={0};   
    struct sockaddr_in s_add,c_add;
    unsigned short portnum=0x8888; 
    printf("Hello,welcome to client !\r\n");

    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == cfd)
    {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");

    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr= inet_addr("127.0.0.1");
    s_add.sin_port=htons(portnum);
    printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);

    if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("connect fail !\r\n");
        return -1;
    }
    printf("connect ok !\r\n");
    write(cfd,"hello tcp socket", strlen("hello tcp socket")+1);

    if(-1 == (recbytes = read(cfd,buffer,1024)))
    {
        printf("read data fail !\r\n");
        return -1;
    }
    printf("read ok\r\nREC:\r\n");
    buffer[recbytes]='\0';
    printf("%s\r\n",buffer);
    getchar();
    close(cfd);
    return 0;
}

makefile:

client:client.o
    gcc -o client client.o
client.o:client.c
    gcc -c client.c -o client.o
clean:
    rm -f *.o client

UDP

a端
a.c

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

int port=6789;
int main(int argc, char** argv) 
{
    int fd; //套接口描述字
    int i=0;
    char buf[80];
    struct sockaddr_in address;//處理網絡通信的地址

    bzero(&address,sizeof(address));
    address.sin_family=AF_INET;
    address.sin_addr.s_addr=inet_addr("127.0.0.1");//這里不一樣
    address.sin_port=htons(port);

    //創(chuàng)建一個 UDP socket

    fd=socket(AF_INET,SOCK_DGRAM,0);//IPV4 SOCK_DGRAM 數(shù)據報套接字(UDP協(xié)議)

    for(i=0;i<20;i++)
    {
        /*
        * sprintf(s, "%8d%8d", 123, 4567); //產生:" 123 4567" 
        * 將格式化后到 字符串存放到s當中
        */
        sprintf(buf,"hello udp socket %d",i);

        /*int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags,const struct sockaddr FAR* to, int tolen);  
        * s:一個標識套接口的描述字。 
        * buf:包含待發(fā)送數(shù)據的緩沖區(qū)卦方。  
        * len:buf緩沖區(qū)中數(shù)據的長度俩檬。 
        * flags:調用方式標志位碾盟《剐兀  
        * to:(可選)指針,指向目的套接口的地址巷疼⊥砗 
        * tolen:to所指地址的長度。 
           */
        sendto(fd,buf,sizeof(buf),0,(struct sockaddr *)&address,sizeof(address));
        sleep(1);
    }

    sprintf(buf,"stop");
    sendto(fd,buf,sizeof(buf),0,(struct sockaddr *)&address,sizeof(address));//發(fā)送stop 命令
    close(fd);
    printf("Messages Sent,terminating\n");

    exit(0);

    return (EXIT_SUCCESS);
}

makefile:

client:a.o
    gcc -o client a.o
a.o:a.c
    gcc -c a.c -o a.o
clean:
    rm -f *.o client

=========================
b端
b.c

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int port=6789;

int main(int argc, char** argv) 
{

    int sin_len;
    char message[256];

    int fd;
    struct sockaddr_in sin;
    printf("Waiting for data from sender \n");

    bzero(&sin,sizeof(sin));
    sin.sin_family=AF_INET;
    sin.sin_addr.s_addr=htonl(INADDR_ANY);
    sin.sin_port=htons(port);
    sin_len=sizeof(sin);

    fd=socket(AF_INET,SOCK_DGRAM,0);
    bind(fd,(struct sockaddr *)&sin,sizeof(sin));

    while(1)
    {
        recvfrom(fd,message,sizeof(message),0,(struct sockaddr *)&sin,&sin_len);
        printf("Response from server:%s\n",message);
        if(strncmp(message,"stop",4) == 0)//接受到的消息為 “stop”
        {

            printf("Sender has told me to end the connection\n");
            break;
        }
    }

    close(fd);
    exit(0);

    return (EXIT_SUCCESS);
}

makefile:

server:b.o
    gcc -o server b.o
b.o:b.c
    gcc -c b.c -o b.o
clean:
    rm -f *.o server

服務端select模型

服務器端
main.cpp

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h> 
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

using namespace std;
bool g_bwillexit = false;
typedef struct _CmdParam
{
    char type;
    char quename[128];
    char conntype;
    
}CmdParam, *PCmdParam;

typedef struct _CmdReply
{
    char reply[20];
}CmdReply;

#define MYPORT 1234    // the port users will be connecting to
#define BACKLOG 1500    // how many pending connections queue will hold
#define BUF_SIZE 1024 

int fd_A[BACKLOG];    // 客戶端連接套接字數(shù)組accepted connection fd
int conn_amount;    // current connection amount

int  writen(int s, char *buff, int len)
{ 
        
    int nLeft,idx, ret;   
    nLeft = len;   
    idx = 0;
    ret = 0;

    while(nLeft>0)
    {   
                if ((ret=send(s, &buff[idx], nLeft,0))== -1)
                {
                        break;
                } 
                nLeft -= ret;   
                idx += ret;
    }
    return idx;
}

int  readn(int s,char *buf,int len)
{
 
         int nRev = 0, recvCount = 0;
         int length = len;

         if(buf == NULL)
          return 0;

        while(length>0)
         {
                  nRev = recv(s,buf+recvCount,length, 0);
                  if(nRev == -1  || nRev == 0)
                  {
                          break;
                  }
                  length -= nRev;
                  recvCount += nRev;
         }
 
         return recvCount;
}

static void  GetMyProcPath(char *buff)
{
   char exec_name [1024] = {0};
   readlink ("/proc/self/exe", exec_name, 1024); 
   char *pSlash = strrchr(exec_name, '/');
   *pSlash = '\0';
   strcpy(buff, exec_name);
   return;
}


int main(int argc, char *argv[])
{
    int sock_fd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct sockaddr_in server_addr;    // server address information
    struct sockaddr_in client_addr; // connector's address information
    socklen_t sin_size;
    int yes = 1;
    char buf[BUF_SIZE];
    int ret;
    int i;


    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket\n");
        exit(1);
    }

    if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
    {
        printf("setsockopt\n");
        exit(1);
    }
    
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(MYPORT);     // short, network byte order
    server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));

    if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) 
    {
        printf("bind error\n");
        exit(1);
    }

    if (listen(sock_fd, BACKLOG) == -1)
    {
        printf("listen\n");
        exit(1);
    }

    printf("listen port %d\n", MYPORT);

    fd_set fdsr;
    int maxsock;
    struct timeval tv;

    conn_amount = 0;
    sin_size = sizeof(client_addr);
    maxsock = sock_fd;
    while (g_bwillexit == false)
    {
        // initialize file descriptor set
        FD_ZERO(&fdsr);
        FD_SET(sock_fd, &fdsr);

        // timeout setting
        tv.tv_sec = 30;
        tv.tv_usec = 0;

        // add active connection to fd set
        for (i = 0; i < BACKLOG; i++)
        {
            if (fd_A[i] != 0)
            {
                FD_SET(fd_A[i], &fdsr);//fd_set fdsr;里面記錄了每個客戶端的套接字
            }
        }

        ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);//開始通過fdsr對每個套接字進行監(jiān)聽
        if (ret < 0)
        {
            printf("select error\n");
            break;
        }
         else if (ret == 0)
        {
            printf("timeout\n");
            continue;
        }

        // check every fd in the set
        // 處理已有的連接通信的,收發(fā)數(shù)據和斷開連接
        for (i = 0; i < conn_amount; i++)
        {
            if (FD_ISSET(fd_A[i], &fdsr))//某個客戶端套接字有響應
            {
                CmdParam cmd ={0};
                ret = readn(fd_A[i], (char *)&cmd, sizeof(cmd));
                if (ret <= 0)
                {   // client close
                    printf("client[%d] close\n", i);
                    close(fd_A[i]);
                    FD_CLR(fd_A[i], &fdsr);
                    fd_A[i] = fd_A[conn_amount-1];
                    fd_A[conn_amount-1]=0;
                    conn_amount--;
                }
                else
                {   // receive data
                    printf("read:%d byetes\n", ret);
                    if (cmd.type == 'c' && (cmd.conntype == 's' || cmd.conntype=='l'))
                    {
                        printf("c and (s or l) command received\n");
                        CmdReply reply = {0};
                        strcpy(reply.reply, "ok!");
                        writen(fd_A[i], (char *)&reply, sizeof(reply));
                    }
                    else  if (cmd.type == 'c')
                    {
                        printf("c command received\n");
                        CmdReply reply = {0};
                        strcpy(reply.reply, "ok!");
                        writen(fd_A[i], (char *)&reply, sizeof(reply));
                    }
                    else if (cmd.type == 'q')
                    {
                        printf("q command received\n");     
                    }
                    else
                    {
                        printf("unknown command received\n");
                        CmdReply reply = {0};
                        strcpy(reply.reply, "unknown cmd");
                        writen(fd_A[i], (char *)&reply, sizeof(reply));
                    }
              }
          }
     }

     // check whether a new connection comes
     // 接受處理新的客戶端連接
     if (FD_ISSET(sock_fd, &fdsr))//sock_fd belongs to server
     {
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
            if (new_fd <= 0)
            {
                printf("accept error\n");
                continue;
            }

            // add to fd queue
            if (conn_amount < BACKLOG)
            {
                fd_A[conn_amount++] = new_fd;
                printf("new connection client[%d] %s:%d\n", conn_amount,
                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                if (new_fd > maxsock)
                    maxsock = new_fd;
            }
            else
            {
                printf("max connections arrive, exit\n");
                CmdReply reply = {0};
                strcpy(reply.reply, "reject");
                writen(new_fd, (char *)&reply, sizeof(reply));
                close(new_fd);
            }
        }
   }
  // close other connections
  for (i = 0; i < BACKLOG; i++)
  {
        if (fd_A[i] != 0)
        {
            close(fd_A[i]);
        }
  }
  return 0;
  
}

makefile:

overpasspull_server:main.o
    g++ -g -o  overpasspull_server main.o
main.o:main.cpp
    g++ -g -c main.cpp -o main.o
clean:
    rm -f *.o overpass

=======================
客戶端
main.cpp

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

#define MYPORT 1234    // the port users will be connecting to

#define BACKLOG 5     // how many pending connections queue will hold
#define BUF_SIZE 200

int  writen(int s, char *buff, int len)
{ 
        
    int nLeft,idx, ret;   
    nLeft = len;   
    idx = 0;
    ret = 0;

    while(nLeft>0)
    {   
                if ((ret=send(s, &buff[idx], nLeft,0))== -1)
                {
                        break;
                } 
                nLeft -= ret;   
                idx += ret;
    }
    return idx;
}

int  readn(int s,char *buf,int len)
{
 
         int nRev = 0, recvCount = 0;
         int length = len;

         if(buf == NULL)
          return 0;

        while(length>0)
         {
                  nRev = recv(s,buf+recvCount,length, 0);
                  if(nRev == -1  || nRev == 0)
                  {
                          break;
                  }
                  length -= nRev;
                  recvCount += nRev;
         }
 
         return recvCount;
}

#define MYPORT 1234
typedef struct _CmdParam
{
        char type;
        char quename[128];
        char conntype;

}CmdParam, *PCmdParam;
typedef struct _CmdReply
{
        char reply[20];
}CmdReply; 

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

    int sockfd,sock_dt; 
    printf("#####################################################\n"); 
    printf("socket test      by pafone   19th,April,2009\n"); 
    printf("#####################################################\n"); 
    struct sockaddr_in my_addr;//local ip info 
    struct sockaddr_in dest_addr; //destnation ip info 

    //int destport = atoi(argv[2]); 
    if(-1 == (sockfd = socket(AF_INET,SOCK_STREAM,0)) ) 
    { 
        printf("error in create socket\n"); 
        exit(0); 
    } 
    dest_addr.sin_family = AF_INET; 
    dest_addr.sin_port = htons(MYPORT); 
    dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    //bzero(&dest_addr.sin_zero,0,8); 
    memset(&dest_addr.sin_zero,0,8); 
    //connect 
    if(-1 == connect(sockfd,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr))) 
    { 
        printf("connect error\n"); 
        exit(0); 
    } 
    int n_send_len; 
    CmdParam cmd ={0};
    cmd.type = 'c';
    //strcpy(cmd.queueip, "10.200.193.169");
    strcpy(cmd.quename, "message_stream");
    //cmd.conntype = 's';
    cmd.conntype = 's';
    //strcpy(cmd.queueport, "3371");
    n_send_len = writen(sockfd, (char *)&cmd, sizeof(cmd));
    printf("%d bytes sent\n",n_send_len); 
    sleep(5);

    CmdReply reply = {0};

    int n_read_len = readn(sockfd, (char *)&reply, sizeof(reply));
    if (n_read_len)
    {
        printf("reply:%s, length:%d\n", reply.reply, n_read_len);
    }
    sleep(5);
    memset(&cmd, 0, sizeof(cmd));
    cmd.type = 'q';
    writen(sockfd, (char *)&cmd, sizeof(cmd));
    
    close(sockfd); 
    
    return 0;
}

makefile:

overpasspull_client:main.o
    g++ -g -o  overpasspull_client main.o
main.o:main.cpp
    g++ -g -c main.cpp -o main.o
clean:
    rm -f *.o overpass

服務端epoll模型

服務端
server.c

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

#define BUFFER_SIZE 40
#define MAX_EVENTS 10

int main(int argc, char * argv[])
{
    int server_sockfd;//服務器端套接字
    int client_sockfd;//客戶端套接字
    int len;
    struct sockaddr_in my_addr;  //服務器網絡地址結構體
    struct sockaddr_in remote_addr; //客戶端網絡地址結構體
    int sin_size;
    char buf[BUFFER_SIZE];  //數(shù)據傳送的緩沖區(qū)
    memset (&my_addr ,0,sizeof(my_addr)); //數(shù)據初始化--清零
    my_addr.sin_family=AF_INET; //設置為IP通信
    my_addr.sin_addr.s_addr=INADDR_ANY;// 服務器IP地址--允許連接到所有本地地址上
    my_addr.sin_port=htons(8000); //服務器端口號
    //創(chuàng)建服務器端套接字--IPv4協(xié)議嚼沿,面向連接通信估盘,TCP協(xié)議
    if((server sockfd=socket(PF_INET, SOCK_STREAM,0))<0)
    {
        perror("socket");return 1 ;
    }
    //將套接字綁定到服務器的網絡地址上
    if (bind(server_sockfd, (struct sockaddr *)&my_addr ,sizeof(struct sockaddr))<0)
    {
        perror("bind");
        return 1;
    }
    //監(jiān)聽連接請求--監(jiān)聽隊列長度為5
    listen(server_sockfd,5);
    sin_size=sizeof(struct sockaddr_in) ;
    //創(chuàng)建一個epoll句柄
    int epoll_fd;
    epoll_fd=epoll_create (MAX_EVENTS);
    if(epoll_fd==-1)
    {
        perror("epoll_create failed");
        exit(EXIT_FAILURE) ;
    }
    struct epoll_event ev;//epoll事件結構體
    struct epoll_event events [MAX_EVENTS];//事件監(jiān)聽隊列
    ev.events=EPOLLIN;
    ev.data.fd=server_sockfd;
    //向epoll注冊server_sockfd監(jiān)聽事件
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD,server_sockfd,&ev)==-1)
    {

      perror("epll_ctl:server_sockfd register failed");
      exit(EXIT_FAILURE);
    }
    int nfds;//epoll監(jiān)聽事件發(fā)生的個數(shù)
    while(1)
    {
        //等待事件發(fā)生
        nfds=epoll_wait(epoll_fd,events ,MAX_EVENTS,-1);
        if(nfds==-1)
        {
            printf("start epoll_wait failed\n");
            break;
        }
        int i;
        for(i=0;i<nfds;i++)
        {
            //客戶端有新的連接請求
            if(events[i].data.fd==server_sockfd)
            {
                //等待客戶端連接請求到達
                if((client_sockfd=accept(server_sockfd, (struct sockaddr * )&remote_addr ,&sin_size))<0)
                {
                    printf("accept client_sockfd failed\n");
                    exit(EXIT_FAILURE);
                }
                //向epoll注冊client_sockfd監(jiān)聽事件
                ev.events=EPOLLIN;
                ev.data.fd=client_sockfd;
                if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD,client_sockfd,&ev)==-1)
                {
                    printf("epoll_ctl:client_sockfd register failed\n");
                    exit(EXIT_FAILURE);
                    printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));
                }
                //客戶端有數(shù)據發(fā)送過來
                else
                {
                    client_sockfd=events[i].data.fd;
                    len=recv(client_sockfd , buf , BUFFER_SIZE,0);
                    if(len<=0)
                    {
                        ev.events=EPOLLIN;
                        ev.data.fd=client_sockfd;
                        epoll_ctl(epoll_fd,EPOLL_CTL_DEL,client_sockfd ,&ev);
                        close(client_sockfd);
                        printf("client exit %d\n" ,client_sockfd);
                        break;
                    }
                    printf("receive from client:%s\n" ,buf) ;
                    send(client_spckfd,buf, BUFFER_SIZE,0);
                }
            }
        }
        return 0;
    }

=============================
客戶端
client.c

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

#define BUFFER_SIZE 40

int main(int argc, char *argv[]){
    int client_sockfd;int len;
    struct sockaddr_in remote_addr; //服務器端網絡地址結構體
    char buf[BUFFER_SIZE]; // 數(shù)據傳送的緩沖區(qū)
    memset(&remote_addr ,θ ,sizeof(remote_addr)); //數(shù)據初始化--清零
    remote_addr.sin_family=AF_INET; //設置為IP通信
    remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");// 服務器IP地址
    remote_addr.sin_port=htons(8000); //服務器端口號
    //創(chuàng)建客戶端套接字--IPv4協(xié)議,面向連接通信骡尽,TCP協(xié)議
    if((client_sockfd=socket(PF_INET , SOCK_STREAM,0))<0)
        {
            perror("client socket creation failed");
            exit(EXIT_FAILURE);
        }
    //將套接字綁定到服務器的網絡地址上
    if(connect(client_sockfd, (struct sockaddr *)&remote_addr , sizeof(struct sockaddr))<0)
    {
        perror ("connect to server failed");
        exit(EXIT_FAILURE);
    }

    //循環(huán)監(jiān)聽服務器請求
    while(1)
        {
        printf("Please input the message:");
        scanf("%s" ,buf);
        //exit
        if(strcmp(buf,"exit")==0)
            {
            break;
            }
            send(client_sockfd, buf , BUFFER_SIZE,0);
            //接收服務端信息
            len=recv(client_sockfd, buf , BUFFER_SIZE,0);
            printf("receive from server :%s\n",buf);
            if(len<0)
            {
                perror("receive from server failed");
                exit(EXIT_FAILURE);
            }
        }
        close(client_sockfd);//關閉套接字
        return 0;
}

makefile:

.PHONY:all
all:server client
server:
    gcc server.c -o server
    gcc client.c -o client
clean:
    rm -f server client

Select與POLL區(qū)別

Select與POLL遣妥,EPOLL都是C種同步的10多路復用模型實現(xiàn)機制,它們的區(qū)別為:
1.select的句柄數(shù)目受限攀细,在linux/posix_types.h頭 文件有這樣的聲明: #define __FD_SETSIZE 1024表示select最多同時監(jiān)聽1024個fd(64位機默認是2048)箫踩。而epoll沒有爱态,它的限制是最大的打開文件句柄數(shù)目。select需要維護一個用來存放大量fd的數(shù)據結構境钟,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大锦担。

2.epoll不會隨著FD的數(shù)目增長而降低效率,select采用輪詢的方式掃描文件描述符慨削,fd數(shù)量越多洞渔,性能越差; epoll維護 了一個隊列,直接看隊列是不是空就可以了缚态。epoll只會對“活躍”的socket進行操作磁椒。這是因為在內核實現(xiàn)中epoll是根據每個fd上面的callback函數(shù)實現(xiàn)的,那么只有活躍socket才會主動去調用callback函數(shù)(把這個句柄加入隊列)

3.無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間玫芦,epoll使用mmap減少復制開銷浆熔,加速內核與用戶空間的消息傳遞。

4.poll本質上和select沒有區(qū)別桥帆,它將用戶傳入的數(shù)組拷貝到內核空間医增,然后查詢每個fd對應的設備狀態(tài),但沒有最大連接數(shù)限制(基于鏈表來存儲的)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末环葵,一起剝皮案震驚了整個濱河市调窍,隨后出現(xiàn)的幾起案子宝冕,更是在濱河造成了極大的恐慌张遭,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件地梨,死亡現(xiàn)場離奇詭異菊卷,居然都是意外死亡,警方通過查閱死者的電腦和手機宝剖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門洁闰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人万细,你說我怎么就攤上這事扑眉。” “怎么了赖钞?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵腰素,是天一觀的道長。 經常有香客問我雪营,道長弓千,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任献起,我火速辦了婚禮洋访,結果婚禮上镣陕,老公的妹妹穿的比我還像新娘。我一直安慰自己姻政,他們只是感情好呆抑,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扶歪,像睡著了一般理肺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上善镰,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天妹萨,我揣著相機與錄音,去河邊找鬼炫欺。 笑死乎完,一個胖子當著我的面吹牛,可吹牛的內容都是我干的品洛。 我是一名探鬼主播树姨,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼桥状!你這毒婦竟也來了帽揪?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤辅斟,失蹤者是張志新(化名)和其女友劉穎转晰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體士飒,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡查邢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了酵幕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扰藕。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖芳撒,靈堂內的尸體忽然破棺而出邓深,到底是詐尸還是另有隱情,我是刑警寧澤笔刹,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布芥备,位于F島的核電站,受9級特大地震影響徘熔,放射性物質發(fā)生泄漏门躯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一酷师、第九天 我趴在偏房一處隱蔽的房頂上張望讶凉。 院中可真熱鬧染乌,春花似錦、人聲如沸懂讯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽褐望。三九已至勒庄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瘫里,已是汗流浹背实蔽。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谨读,地道東北人局装。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像劳殖,于是被迫代替她去往敵國和親铐尚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容

  • 必備的理論基礎 1.操作系統(tǒng)作用: 隱藏丑陋復雜的硬件接口哆姻,提供良好的抽象接口宣增。 管理調度進程,并將多個進程對硬件...
    drfung閱讀 3,537評論 0 5
  • 本文摘抄自linux基礎編程 IO概念 Linux的內核將所有外部設備都可以看做一個文件來操作矛缨。那么我們對與外部設...
    VD2012閱讀 1,021評論 0 2
  • 1. 硬鏈接和軟連接區(qū)別 硬連接-------指通過索引節(jié)點來進行連接爹脾。在Linux的文件系統(tǒng)中,保存在磁盤分區(qū)...
    杰倫哎呦哎呦閱讀 2,251評論 0 2
  • 2018-11-06 這一塊操作系統(tǒng)主要分為兩個部分劳景,一個部分是書本上操作系統(tǒng)的知識誉简,還有一部門是linux的相關...
    zuoerfeng閱讀 2,222評論 0 1
  • 網絡編程基礎網絡編程,首先了解計算機網絡體系結構是有必要的瓮钥,著重掌握TCP筋量、IP協(xié)議,理解socket的概念碉熄,理解...
    zhile_doing閱讀 1,862評論 0 1