for (int t = 0; t < physicalCoreCount; t ) {
int pid = fork();
if (pid==0) {
// setting up epoll
epoll_fd = epoll_create1(0);
event.data.fd = listenSocketfd;
event.events = EPOLLIN | EPOLLET;
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listenSocketfd, &event);
events = (epoll_event*)calloc(LISTENQ, sizeof(event));
//*****/
while (1) {
int ndfs = epoll_wait(epoll_fd, events, curfdCount, -1);
if (ndfs==-1) {
continue;
}
for (int i=0; i < ndfs; i ) {
if (events[i].data.fd == listenSocketfd) { // original listener
int new_connfd = accept(events[i].data.fd, (sockaddr*)&clientaddr, &clientlen);
if (new_connfd==-1) {
if (errno==EAGAIN || errno==EWOULDBLOCK) {
continue;
}
else exitPerrorLog("accept()");
}
set_non_block(new_connfd);
event.events = EPOLLIN | EPOLLET;
event.data.fd = new_connfd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_connfd, &event) < 0)
exitPerrorLog("epoll_ctl");
clientaddrOfFd[new_connfd] = new sockaddr_in();
memcpy(clientaddrOfFd[new_connfd], &clientaddr, sizeof(clientaddr));
curfdCount ;
}
else {
process(events[i].data.fd, clientaddrOfFd[events[i].data.fd]);
//epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, &event);
if (curfdCount > 10000) curfdCount = 10000; //curfdCount--;
}
}
}
}
}
出現問題是因為我正在嘗試實作持久連接(回應后不關閉)。然而,孩子 0 可以接受()一個套接字檔案描述符 X,對其進行處理,但后來孩子 1 可以接受()相同的檔案描述符。由于我沒有關閉 child 0 上的連接(以實作 HTTP1.1 keep-alive),現在 2 個孩子正在讀/寫同一個檔案描述符。
有什么方法可以防止這個問題?謝謝你。
編輯:重要更新:所以主要問題是我認為 2 個相同的 FD 意味著它是相同的連接,我想避免這種情況,因為它會導致 2 個孩子讀/寫相同的東西。如果這種情況沒有發生(讀/寫重疊),那么我認為問題就解決了。有人可以確認嗎?
uj5u.com熱心網友回復:
您正在創建多個 epoll 實體并在每個實體的偵聽套接字上注冊邊緣觸發事件。自然地,當新連接可以接受時,您將從每個人那里得到一個事件。但是,只有一個行程可以成功接受每個連接。正如評論中所觀察到的,兩個不同的子行程可能會接受在各自行程中分配了相同檔案描述符編號的連接,但這并不意味著它們參考同一個套接字。
您有多種選擇,但其中最突出的是:
使用單個 epoll 實體,由所有行程共享。您可以通過在分叉任何子級之前讓父級創建它來自動獲得它。在這種情況下,只有一個孩子會收到每個邊沿觸發事件。當然,如果孩子們打算注冊只應該由他們接收的事件,那么這不會很好地作業。
只是接受(沒有雙關語)多個行程將在連接可用時接收事件,并處理它。這似乎是你現在正在做的事情(通過忽略
EAGAIN和EWOULDBLOCK錯誤accept()),我認為沒有特別的理由為什么你不應該繼續這樣做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/338886.html
上一篇:將字串陣列傳遞給另一個函式
下一篇:列印降序陣列C
