我想制作非块TCP接收器,以便cilent可以定期向服务器发送消息(即每10分钟更新一次信息)。
我在本地机器上测试它。 'return_status'值表示'bind,accept,connect和write'正常工作,但read总是返回-1。有人可以解释一下吗?感谢
客户端代码。
#define CONTROLPORT 6000
int main(void)
{
int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];
control_sock = socket(AF_INET, SOCK_STREAM, 0);
control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);
return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
fcntl(control_sock, F_SETFL, O_NONBLOCK);
return_status = listen(control_sock, 1);
cout << return_status << endl;
return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len);
cout << return_status << endl;
while(1){
return_status = read(control_sock,control_message,sizeof(control_message));
cout << return_status << endl;
}
}
发件人方代码
#define CONTROLPORT 6000
using namespace std;
int main(void)
{
int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];
control_message[10] = 111;
control_sock = socket(AF_INET, SOCK_STREAM, 0);
control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);
return_status = connect(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
cout << return_status << endl;
return_status = write(control_sock,control_message,sizeof(control_message));
cout << return_status << endl;
}
答案 0 :(得分:0)
您已将套接字设置为非阻塞,因此accept
在某个连接之前不会阻塞。 accept
将返回EAGAIN或EQOULDBLOCK。检查错误。如果没有此检查,您的代码将继续执行read
。它返回-1(再次检查errno),因为首先没有建立连接。
您必须使用select
,poll
或epoll
来查看非阻塞套接字上的事件。这是为了弄清楚是否有人在已建立的连接上连接/发送数据。
答案 1 :(得分:0)
在您的情况下,我不认为非阻塞服务器是必要的。如果您的确是这个意思,那么您应该看一下select()
,epoll
和类似内容。至于你的代码,还有几个问题:
accept()
应该在while循环中。accept()
成功返回已接受套接字的描述符,此描述符应传递给read()
。O_NONBLOCK
,因此accept()
会立即返回。如果不接受任何联系,则errno
将设置为EAGAIN
或EWOULDBLOCK
。修改后的代码:
int main(void)
{
int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];
control_sock = socket(AF_INET, SOCK_STREAM, 0);
control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.7.134");
control_addr.sin_port = htons(CONTROLPORT);
return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
//fcntl(control_sock, F_SETFL, O_NONBLOCK);
return_status = listen(control_sock, 1);
cout << return_status << endl;
while(1){
return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len);
cout << return_status << endl;
return_status = read(return_status,control_message,sizeof(control_message));
cout << return_status << endl;
}
}
答案 2 :(得分:0)
如果您打算进行非阻塞套接字编程,您必须了解read()将返回-1,当没有任何内容要读取时,errno设置为EAGAIN / EWOULDBLOCK,并使用select()告诉你什么时候不会。
NB 4是Unix,Solaris,HP-UX,AIDA,Linux等中的有效套接字FD ...