gpt4 book ai didi

c - 对非阻塞套接字使用 select()

转载 作者:太空狗 更新时间:2023-10-29 17:18:05 25 4
gpt4 key购买 nike

我正在尝试使用 select 函数在服务器和 1 个客户端(不再)之间进行非阻塞 i/o,通信流畅(可以随时发送,另一个无需等待发送即可接收) .我找到了一个包含一些代码的教程,并尝试将其调整为适合我的。这就是我所拥有的 -

服务器

#define PORT "4950"
#define STDIN 0

struct sockaddr name;

void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}


// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET)
return &(((struct sockaddr_in*)sa)->sin_addr);

return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int agrc, char** argv) {
int status, sock, adrlen, new_sd;

struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results

//store the connecting address and size
struct sockaddr_storage their_addr;
socklen_t their_addr_size;

fd_set read_flags,write_flags; // the flag sets to be used
struct timeval waitd; // the max wait time for an event
int sel; // holds return value for select();

//socket infoS
memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address

//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}

//make socket
sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sock < 0) {
printf("\nserver socket failure %m", errno);
exit(1);
}

//allow reuse of port
int yes=1;
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}

//unlink and bind
unlink("127.0.0.1");
if(bind (sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nBind error %m", errno);
exit(1);
}

freeaddrinfo(servinfo);

//listen
if(listen(sock, 5) < 0) {
printf("\nListen error %m", errno);
exit(1);
}
their_addr_size = sizeof(their_addr);

//accept
new_sd = accept(sock, (struct sockaddr*)&their_addr, &their_addr_size);
if( new_sd < 0) {
printf("\nAccept error %m", errno);
exit(1);
}

set_nonblock(new_sd);
cout<<"\nSuccessful Connection!";

char* in = new char[255];
char* out = new char[255];
int numSent;
int numRead;


while(1) {

waitd.tv_sec = 10;
FD_ZERO(&read_flags);
FD_ZERO(&write_flags);
FD_SET(new_sd, &read_flags);

if(strlen(out) != 0)
FD_SET(new_sd, &write_flags);

sel = select(new_sd+1, &read_flags, &write_flags, (fd_set*)0, &waitd);
if(sel < 0)
continue;

//socket ready for reading
if(FD_ISSET(new_sd, &read_flags)) {
FD_CLR(new_sd, &read_flags);

memset(&in, 0, sizeof(in));

if(recv(new_sd, in, sizeof(in), 0) <= 0) {
close(new_sd);
break;
}
else
cout<<"\n"<<in;
} //end if ready for read

//socket ready for writing
if(FD_ISSET(new_sd, &write_flags)) {

FD_CLR(new_sd, &write_flags);
send(new_sd, out, strlen(out), 0);
memset(&out, 0, sizeof(out));
}
} //end while

cout<<"\n\nExiting normally\n";
return 0;
}

客户端(基本上相同,只是减去一个接受调用)-

#define PORT "4950"

struct sockaddr name;

void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET)
return &(((struct sockaddr_in*)sa)->sin_addr);

return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int agrc, char** argv) {
int status, sock, adrlen;

struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results

fd_set read_flags,write_flags; // the flag sets to be used
struct timeval waitd; // the max wait time for an event
int sel; // holds return value for select();

memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address

//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}

//make socket
sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sock < 0) {
printf("\nserver socket failure %m", errno);
exit(1);
}

if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nclient connection failure %m", errno);
exit(1);
}

cout<<"\nSuccessful connection!";

set_nonblock(sock);

char* out = new char[255];
char* in = new char[255];
int numRead;
int numSent;

while(1) {

waitd.tv_sec = 10;
FD_ZERO(&read_flags);
FD_ZERO(&write_flags);
FD_SET(sock, &read_flags);

if(strlen(out) != 0)
FD_SET(sock, &write_flags);


sel = select(sock+1, &read_flags, &write_flags, (fd_set*)0, &waitd);
if(sel < 0)
continue;

//socket ready for reading
if(FD_ISSET(sock, &read_flags)) {
FD_CLR(sock, &read_flags);

memset(&in, 0, sizeof(in));

if(recv(sock, in, sizeof(in), 0) <= 0) {
close(sock);
break;
}
else
cout<<"\n"<<in;
} //end if ready for read

//socket ready for writing
if(FD_ISSET(sock, &write_flags)) {
FD_CLR(sock, &write_flags);
send(sock, out, strlen(out), 0);
memset(&out, 0, sizeof(out));
}
} //end while

cout<<"\n\nExiting normally\n";
return 0;
}

问题是当我运行它们时,没有任何反应。我可以输入一个并按回车键,另一个屏幕上什么也没有显示(反之亦然)。这不是我要调试的全部信息,这是我第一次真正尝试使用 select,所以我想也许我只是不知道一些简单的事情。如果发现任何错误或奇怪的地方,请指出,我们将不胜感激。

最佳答案

The problem is that when I run them, nothing happens.

真正的问题是人们多年来一直在粘贴 Beej 的东西而不理解它。这就是为什么我不太喜欢那个指南的原因;它提供了大量代码,但并未真正详细解释它们。

您没有阅读任何内容,也没有发送任何内容;没有 fgets、scanf、cin 等。这是我要做的:

FD_SET(sock, &read_flags);
FD_SET(STDIN_FILENO, &read_flags);

/* .. snip .. */

if(FD_ISSET(STDIN_FILENO, &read_flags)) {
fgets(out, len, stdin);
}

这将监视 stdin 并在输入可用时从中读取;然后,当套接字可写时 (FD_ISSET(sock, &write_flags)),它将发送缓冲区。

关于c - 对非阻塞套接字使用 select(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6715736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com