【发布时间】:2015-11-21 14:13:20
【问题描述】:
程序创建了n个线程来模拟分布式系统中的n个节点,每个节点都有一个监听的socket,每个线程可以通过connect调用与n-1个其他线程通信。
每个线程都会调用 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 {...}
【问题讨论】:
-
绝对没有规则禁止这种情况发生,即使您的所有代码都是正确的。保证套接字不会阻塞的唯一方法是将其设置为非阻塞。否则,您所做的相当于检查磁盘上是否有可用空间,然后附加到文件中——有 曾 空闲空间并不能保证 将追加时成为可用空间。套接字是可读的并不能保证它以后将 可读。