我只想在连接套接字后等待,看看是否可以写入它。所以我创建并连接我的插座并使用"选择"来完成这项工作,除非......没有正确排序。
这是我的代码:
int SocketToBox(char boxIp[INET6_ADDRSTRLEN], int port)
{
struct sockaddr_in boxAddress;
int sock = -1;
if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) {
printf("%s : socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0) : errno = '%s'.n", __func__, strerror(errno));
return (-1);
}
memset(&boxAddress, 0, sizeof(boxAddress));
boxAddress.sin_family = AF_INET;
boxAddress.sin_port = htons(port);
if (inet_pton(AF_INET, boxIp, &boxAddress.sin_addr) != 1) {
printf("%s : inet_pton(AF_INET, boxIp<'%s'>, &boxAddress.sin_addr) : errno = '%s'.n", __func__, boxIp, strerror(errno));
close(sock);
return (-1);
}
if (connect(sock, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) == -1) {
if (errno != EINPROGRESS) {
printf("%s : connect(sock<%d>, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) : errno = '%s'.n", __func__, sock, strerror(errno));
close(sock);
return (-1);
}
}
return (sock);
}
int main(void)
{
int sock;
fd_set writeFdSet;
char *message = "Hello World !";
if ((sock = SocketToBox("192.192.192.192", 2000)) == -1) {
printf("%s : SocketToBox("192.192.192.192", 2000) : callstack.n", __func__);
return (1);
}
FD_ZERO(&writeFdSet);
FD_SET(sock, &writeFdSet);
if (select(sock + 1, NULL, &writeFdSet, NULL, NULL) == -1) {
printf("%s : select(sock<%d> + 1, NULL, &writeFdSet, NULL, NULL) : errno = '%s'.", __func__, sock, strerror(errno));
return (1);
}
if (FD_ISSET(sock, &writeFdSet)) {
printf("socket UP.n");
if (send(sock, message, strlen(message), MSG_DONTWAIT) == -1) {
printf("%s : send(sock<%d>, message<'%s'>, strlen(message)<%zu>, MSG_DONTWAIT) : errno '%s'.n", __func__, sock, message, strlen(message), strerror(errno));
return (1);
}
printf("Message sended.n");
} else {
printf("socket DOWN.n");
}
FD_ZERO(&writeFdSet);
if (sock == -1) {
close(sock);
}
return (0);
}
和我的输出:
socket UP.
main : send(sock<3>, message<'Hello World !'>, strlen(message)<13>, MSG_DONTWAIT) : errno 'Connection timed out'.
我错过了什么?选择返回 1,我也不明白!为什么是 1 而不是 0?为什么我的套接字在发送失败时被选择标记为"可写"?我可以向你保证,我不能ping192.192.192.192。
从select
手册页:
成功后,
select()
和pselect()
返回三个返回的描述符集中包含的文件描述符数
这就是 select
函数为您返回1
的原因:它返回集合中设置的一个描述符。
对于第二个问题,也来自手册页:
如果可以执行相应的 I/O 操作(例如,
read(2)
不阻塞,或者足够小的write(2)
),则认为文件描述符已准备就绪。
和
将监视
writefds
中的那些,以查看是否有空间可用于写入(尽管大型写入仍可能阻塞)
因此,select
会告诉您的是,描述符内部缓冲区中有可用空间,它没有说明数据是否真的可以发送。
因为写入未连接的套接字不会阻塞 - 这是选择唯一可以保证你的事情。