在 C++网络,使用 select 我首先必须listen() 和accept() 吗?
我试图允许多个客户端使用 select 连接到主机。我是否必须连接每个端口,告诉它们移至不同的端口,然后在新端口上重新连接?或者选择允许我将多个客户端连接到同一端口?
这是客户端代码:
int rv;
int sockfd, numbytes;
if ((rv = getaddrinfo(hostName, hostPort, &hints, &servinfo)) != 0) {
cout << "Could not get server address.\n";
exit(1);
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("Client: no socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("Client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "Unable to connect to server.\n");
exit(2);
}
FD_SET(sockfd, &masterSet);
这是服务器代码:
int rv = getaddrinfo(NULL, port, &hints, &res);
int yes = 1;//Not sure what this is for, found it in Beej's
if(rv != 0){
cout<< "Error, nothing matches criteria for file descriptor.\n";
exit(1);
}
int fdInit;
for(temp = res; temp != NULL; temp = temp->ai_next){
if((fdInit = socket(temp->ai_family, temp->ai_socktype, temp->ai_protocol)) == -1){
cout << "This is not the fd you're looking for. Move along.\n";
continue; //This is not the fd you're looking for, move along.
}
if(setsockopt(fdInit, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
cout << "Doom has fallen upon this set socket.\n";
perror("setsockopt");
exit(1); //Unable to set socket, exit program with code 1
}
if(bind(fdInit, temp->ai_addr, temp->ai_addrlen) == -1){
cout << "Could not bind fd\n";
close(fdInit);
continue; //Could not bind fd, continue looking for valid fd
}
break; //If a valid fd has been found, stop checking the list
}
if(temp==NULL){
cout<<"Server failed to bind a socket\n";
exit(2);
}
cout << fdInit << endl;
//Setup the file descriptor for initial connections on specified port
freeaddrinfo(res);
FD_SET(fdInit, &masterSet);
任何帮助都会非常好!谢谢。
I'm trying to allow multiple clients to connect to a host using select. Will I have to connect each one, tell them to move to a different port, and then reconnect on a new port? Or will select allow me to connect multiple clients to the same port?
This is the client code:
int rv;
int sockfd, numbytes;
if ((rv = getaddrinfo(hostName, hostPort, &hints, &servinfo)) != 0) {
cout << "Could not get server address.\n";
exit(1);
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("Client: no socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("Client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "Unable to connect to server.\n");
exit(2);
}
FD_SET(sockfd, &masterSet);
This is the server code:
int rv = getaddrinfo(NULL, port, &hints, &res);
int yes = 1;//Not sure what this is for, found it in Beej's
if(rv != 0){
cout<< "Error, nothing matches criteria for file descriptor.\n";
exit(1);
}
int fdInit;
for(temp = res; temp != NULL; temp = temp->ai_next){
if((fdInit = socket(temp->ai_family, temp->ai_socktype, temp->ai_protocol)) == -1){
cout << "This is not the fd you're looking for. Move along.\n";
continue; //This is not the fd you're looking for, move along.
}
if(setsockopt(fdInit, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
cout << "Doom has fallen upon this set socket.\n";
perror("setsockopt");
exit(1); //Unable to set socket, exit program with code 1
}
if(bind(fdInit, temp->ai_addr, temp->ai_addrlen) == -1){
cout << "Could not bind fd\n";
close(fdInit);
continue; //Could not bind fd, continue looking for valid fd
}
break; //If a valid fd has been found, stop checking the list
}
if(temp==NULL){
cout<<"Server failed to bind a socket\n";
exit(2);
}
cout << fdInit << endl;
//Setup the file descriptor for initial connections on specified port
freeaddrinfo(res);
FD_SET(fdInit, &masterSet);
Any help would be excellent! Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
TCP 连接由连接两端的 IP 地址和端口号来标识。因此,有很多客户端(通常具有随机分配的端口号)连接到单个服务器端口是很好的。
您创建一个套接字并将其
bind()
到一个端口,在该端口上listen()
,然后等待客户端来敲击它。如果您不介意阻塞,您可以直接调用accept()
,但您不会执行任何超时循环或任何操作。否则,您可以在侦听套接字上select()
(当客户端尝试连接时该套接字将变为可读),然后调用accept()
。accept()
将返回一个新创建的套接字,这是与客户端通信的实际套接字。原来的监听套接字继续监听,并且可以在其上接受更多连接。通常使用
select()
循环来查找侦听套接字和任何已连接套接字的可读性。然后,当select()
返回时,您只需检查侦听套接字是否可读,如果是,则accept()
;否则寻找一个可读的已连接套接字并处理它。TCP connections are identified by the IP address and port number of both ends of the connection. So it's fine to have lots of clients (which will generally have randomly assigned port numbers) to connect to a single server port.
You create a socket and
bind()
it to a port on which tolisten()
, and then wait for clients to come knocking on it. If you don't mind blocking you can just callaccept()
on it directly, but you won't get to do any timeout looping or anything. Otherwise you canselect()
on the listening socket, which will become readable when a client is attempting to connect, and then callaccept()
.accept()
will return a newly created socket, which is the actual socket to talk to the client on. The original listening socket continues to listen, and more connections can be accepted on it.It's typical to use a
select()
loop to look for readability on the listening socket and any of the connected sockets. Then whenselect()
returns you simply check whether the listening socket was readable, and if so,accept()
; otherwise look for a readable connected socket and handle it.许多客户端可以连接到同一个端口,
您必须先侦听,然后选择,
当选择告诉您有一个新连接时,然后接受。它告诉您客户端通过标记对套接字 fd 的读取来连接。
many clients can connect to the same port
you must listen first then select
when select tells you you have a new connection then accept. It tells you that client connected by flagging a read on your socket fd.
您必须将服务器套接字标记为这样(
listen(2)
),但仅在从select(2)
返回时调用accept(2)
它变得可读 - 这意味着新的连接请求正在等待。请注意,如果您不使用非阻塞套接字,
select(2)之间就有竞争的机会 code> 返回并调用
accept(2)
- 连接客户端可能会在此期间放弃尝试 - 因此您仍然可以阻止。You have to mark server socket as such (
listen(2)
) but only callaccept(2)
upon return fromselect(2)
when it becomes readable - that means new connection request is pending.Please note that if you are not working with non-blocking sockets there's a chance for a race between
select(2)
returning and callingaccept(2)
- the connecting client may drop the attempt during that time - so you can still block.