linux下I O復用與epoll實際使用(二)

2021-08-28 20:58:00 字數 3600 閱讀 6582

為了使網路程式具有可移植性可以呼叫以下函式進行網路位元組數的轉換。

#include uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

socket位址資料型別及相關函式

sockaddr資料結構

tcpsocket 實現

實現模型:

1.伺服器端 socket -> bind -> listen -> accept(阻塞,三次握手)-> send。

2.客戶端 socket -> connect(阻塞,三次握手)-> rcv。

上一節我們已經比較過select與epoll的優缺點。

現在直接上select和epoll的示例**:

**在(一)的基礎上修改的

server端

#include#include#include#include#include#include#include#include#include#include#include#define _select

int gsetnonblocking(int fd)

/*往 epoll 描述符新增套接字*/

void gaddfd(int epollfd,int fd,bool oneshoot)

ret=epoll_ctl(epollfd,epoll_ctl_add,fd,&event);

gsetnonblocking(fd);

}void gdelfd(int epollfd,int fd,bool oneshoot)

ret=epoll_ctl(epollfd,epoll_ctl_add,fd,&event);

if(ret!=0)

}}void gctrlfd(int epollfd,int fd,bool oneshoot)

ret=epoll_ctl(epollfd,epoll_ctl_add,fd,&event);

if(ret!=0) }

}int main(int argc,char *argv)

}} ret=select(maxfd+1,&rfds,&wfds,null,null);

if(ret>0)

}if(k==array_size)

}}else if(j!=0 && fd_isset(array[j],&rfds))

}else if(0==s)

else}}

} #else

number=epoll_wait(epollfd,event,512,-1);

if(number < 0 && errno !=eintr)

for(i=0;i%d:%s\n",errno,strerror(errno));

continue;

}/*設定連線套接字epolloneshot*/

gaddfd(epollfd,connfd[count],false);

count++;

if(count>19)

else if(ret==0)

else if(errno == ewouldblock)

else if(errno == epipe)

ret=recv(connfd[j],text,512,0);}}

}}}#endif }

}

client端

#include #include #include #include #include #include #include #include #include #include #include #include #define path "tempfile.socket"

int sock;

void sig(int sig)

int main(int argc, char *argv)

signal(sigint, sig);

sock = socket(af_inet, sock_stream, 0);

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = af_inet;

addr.sin_port = htons(atoi(argv[1]));

addr.sin_addr.s_addr = inet_addr("127.0.0.1");

connect(sock, (struct sockaddr *)&addr, sizeof(addr));

int old = fcntl(sock, f_getfl);

int newoption = old | o_nonblock;

fcntl(sock, f_setfl, newoption);

char buf[512];

memset(buf, 0, sizeof(buf));

int epollfd = epoll_create(5);

struct epoll_event event[128];

struct epoll_event e1,e2;

e1.data.fd = sock;

e1.events = epollin | epollet;

epoll_ctl(epollfd, epoll_ctl_add, sock, &e1);

e2.data.fd = stdin_fileno;

e2.events = epollin | epollet;

epoll_ctl(epollfd, epoll_ctl_add, stdin_fileno, &e2);

int nr;

int ret;

int i;

while (1)

for(i = 0; i < number; ++i)

write(stdout_fileno, buf, nr);

}else if (event[i].data.fd == stdin_fileno && (event[i].events & epollin))

ret = write(sock, buf, nr);

if (ret == 0 && errno == eintr)

else if (ret < 0)

printf("send [%d]byte\n", ret);

}} }

close(sock);

return 0;

}

執行結果:

Linux下I O復用模型

以下內容引述至 linux unix系統程式設計手冊 常見的程式使用的i o模型都是單個程序每次只在乙個檔案描述符上執行i o操作,每次i o系統呼叫會阻塞直到完成資料傳輸。對於許多應用來說,傳統的阻塞式i o模型已經足夠了,但這不代表所有的應用都能得到滿足。非阻塞式i o可以讓我們周期性地檢查 輪...

linux下的I O復用函式

select系統呼叫 select系統呼叫的功能是 在一段時間裡監聽使用者感興趣的檔案描述符上的可讀,可寫 異常等事件。這是linux上的select系統呼叫的原型 各個引數說明 nfds指定被監聽的檔案描述符的總數,它通常被設定為最大的檔案描述符的值加一,因為檔案描述符是從 0開始的。readfd...

Linux下的i o復用 select

1 i o復用 乙個程序或者乙個執行緒能夠同時對多個檔案描述符 socket 提供服務,伺服器上的程序或執行緒如何將多個檔案描述符統一監聽,當任意乙個檔案描述符上有事件發生,其都能及時處理。2 select函式 啟動監聽 int select int nfds,fd set readfds fd s...