c - select() 适用于 STDIN 但不适用于套接字
问题描述
我有以下用于 TCP 客户端的 C 代码:
#define PORT 8888
void connexion(int sock)
{
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(sock, &rfds);
char buf[512];
retval = select(3, &rfds, NULL, NULL, NULL);
if (retval == -1)
perror("select()");
else if (retval) {
read(retval, buf, 512);
printf("\nbuf: %s", buf);
memset(buf, 0, 512);
}
connexion(sock);
}
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
connexion(sock);
}
我尝试在不停止读取套接字的情况下读取标准输入。确实,我需要能够在写消息的同时接收消息。为此,我使用了选择功能。但是我只从终端接收消息,从不从服务器接收消息。
服务器仍然收到了来自客户端的套接字......这段代码有什么问题?
先感谢您。
解决方案
你没有select
以正确的方式使用,更换
retval = select(3, &rfds, NULL, NULL, NULL);
经过
retval = select(sock+1, &rfds, NULL, NULL, NULL);
select() 为标准输入工作...
这适用于标准输入,因为标准输入为 1,因此小于 3
在那之外
read(retval, buf, 512);
不做你期望的,做
if (FD_ISSET(sock, &rfds)) {
read(sock, buf, 512);
printf("buf from socket: %s\n", buf);
}
if (FD_ISSET(stdin, &rfds)) {
read(stdin, buf, 512);
printf("buf from stdin: %s\n", buf);
}
警告如果您在套接字上读取并且未发送/读取空字符,因为printf
将具有未定义的行为,可能会保存读取长度以在末尾添加空字符
如果套接字已关闭或者您在stdin
两者上都达到 EOFread
可能什么也没有读到,所以最好检查它们的结果
不要else
在两者之间使用 an,if
因为您可以同时获得两者的输入
您的终端递归可以替换为循环
在您printf
之前而不是之后生成换行符很奇怪,在刷新输出之后执行
在主要
char *hello = "Hello from client"; char buffer[1024] = {0};
未使用
推荐阅读
- css - 我可以在 react-responsive-carousel 中自定义 Carousel-indicators 吗
- javascript - 如何在我的 auth.tsx 文件上使用 typescript 文件
- python - 在python中返回一个数字及其平方的数组
- r - 使用 for 循环迭代列名会导致 R 中的 NAargument 错误
- java - 对象引用如何在包装类对象和自定义对象中工作?
- r - 错误:“RLumShiny”的包或命名空间加载失败
- c++ - protobuf 定义映射时用于存储的 C++ 类型
场地 - javascript - 我想使用 @ngneat/cashew 和拦截器来缓存 HTTP 请求,这可能吗?
- date - Cockroach-DB - 错误计算日期差
- javascript - vuejs:仅为每个 x 元素创建 v-row