程序創建n個線程來模擬分佈式系統中的n個節點,每個線程有一個偵聽的套接字,每個線程可以通過連接與n-1個其他線程通信調用。AF_UNIX套接字:select()在沒有東西可讀時觸發
每個線程都會調用select()來查看是否有可用的內容,如果有,則接受並保存數據。
我使用帶有標誌FIONREAD的ioctl來檢查可讀取的字節數並進行適當的讀取調用。之後,新的fd(來自accept())被關閉。
監聽套接字阻塞。 O_NONBLOCK未設置。
所有n個線程運行相同的功能。在函數中聲明的所有變量都使用線程本地存儲。
我沒有明確的同步。多個線程可以嘗試一次連接到同一個套接字。現在
,問題是,過一段時間,在接收側的線程的select()注意到一些新的東西,但可用的字節量爲0,它不應該。這種情況不一致。
如果有人能指出我應該看的地方,那將會很棒。謝謝!
創建襪子
if ((nptr->sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
fd_max = nptr->sock > fd_max ? nptr->sock : fd_max;
int ok=1;
setsockopt(nptr->sock, SOL_SOCKET, SO_REUSEADDR, &ok, sizeof(int));
nptr->addr.sun_family = AF_UNIX;
snprintf(nptr->addr.sun_path, 20, "%d", nptr->id);
//strncpy(nptr->addr.sun_path, sock_path, 20);
if (bind(nptr->sock, (struct sockaddr*)&(nptr->addr), sizeof(struct sockaddr_un)) < 0) {
perror("bind");
exit(1);
}
/* socket, max connections */
if (listen(nptr->sock, 2*tot_node) < 0) {
perror("listen");
exit(1);
}
送東西
for (t=0; t<tot_node; t++) {
...
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Node %d: trying to req node %d... ", self->id, node_catalog[t]->id);
if (connect(fd, (struct sockaddr*)&(node_catalog[t]->addr), sizeof(struct sockaddr_un)) == -1) {
perror("connect");
exit(1);
}
buf[0] = TYPE_REQ;
buf[1] = self->id;
buf[2] = ts;
buf[3] = rsc;
write (fd, buf, 4*sizeof(int));
//close(fd);
printf("Node %d: sent req for resource %d to %d\n", self->id, rsc, node_catalog[t]->id);
}
usleep(TS_UPDATE_ITV);
接收的東西
FD_ZERO(&readset);
FD_SET(self->sock, &readset);
t = pselect(self->sock+1, &readset, NULL, NULL, &tout, NULL);
if (t > 0 && FD_ISSET(self->sock, &readset)) {
com_fd = accept(self->sock, NULL, NULL);
ioctl(com_fd, FIONREAD, &t);
#ifdef DEBUG
printf(" Node %d: received %d bytes of data\n", self->id, t);
#endif
read(com_fd, buf, t);
close(com_fd);
dptr = (int *)buf;
rsc = t/(sizeof(int)); /* var reuse. this is the count of ints to read */
for (t=0; t<rsc;) {
static __thread int nid, nts, nrsc;
#ifdef DEBUG
printf(" Node %d: data rcvd: %d %d %d %d", self->id, *dptr, *(dptr+1), *(dptr+2), *(dptr+3));
#endif
if (*dptr == TYPE_REQ) {
... } else {...}
即使您的所有代碼都是正確的,但絕對沒有禁止這種情況發生的規則。確保套接字不會阻塞的唯一方法是將其設置爲非阻塞。否則,您正在做相當於檢查磁盤上是否有可用空間,然後追加到文件的情況 - 那裏有*空閒空間並不能保證您追加時會有*空閒空間。 socket *是*可讀的,並不能保證它*將* *在以後可讀*。 –