gpt4 book ai didi

c++ - 尝试保存与成员 vector 的连接 - 一次只保存一个

转载 作者:行者123 更新时间:2023-11-28 02:55:11 27 4
gpt4 key购买 nike

我正在尝试编写一个简单的服务器应用程序,它可以从多个客户端获取连接,并将这些连接保存到一个 vector 中以供另一个对象读取。

我有一个类 NetworkConnection,它是另一个类 Manager 的成员。这是我的主要方法:

int main(int argc, const char* argv[])
{
RoutingManager *manager = new RoutingManager();
manager->ParseInputFile("topo.txt", 10, 3, " ");

manager->myConnection = new NetworkConnection("localhost", "7777");
manager->myConnection->SetSocketHints();
manager->myConnection->PopulateAddressInfo();
manager->myConnection->BindSocket();
manager->myConnection->ListenForConnections();

return 0;
}

我省略了很多细节,因为它们与您可以在任何地方找到的通用套接字编程指南非常相似……主要问题是在调用期间:

int
NetworkConnection::ListenForConnections()
{
char s[INET6_ADDRSTRLEN];

if (listen(socketFd, 15) == -1) {
perror("listen");
exit(1);
}
/*
sigAction.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sigAction.sa_mask);
sigAction.sa_flags = SA_RESTART;
*/
if (sigaction(SIGCHLD, &sigAction, NULL) == -1) {
perror("sigaction");
exit(1);
}

printf("server: waiting for connections...\n");

while(1) { // main accept() loop
sin_size = sizeof theirAddress;
int new_fd = accept(socketFd, (struct sockaddr *)&theirAddress, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}

inet_ntop(theirAddress.ss_family,
get_in_addr((struct sockaddr *)&theirAddress),
s, sizeof s);
printf("server: got connection from %s\n", s);

if (!fork()) { // this is the child process
close(socketFd); // child doesn't need the listener

NodeConnection nc = NodeConnection();

char ipstr[INET6_ADDRSTRLEN];
getpeername(new_fd, (struct sockaddr*)&theirAddress, &sin_size);
struct sockaddr_in *s = (struct sockaddr_in *)&theirAddress;
int port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, nc.ipstr, sizeof ipstr);

nc.fd = new_fd;
nc.theirAddress = theirAddress;
nc.sin_size = sin_size;
nc.port = port;

newConnections.push_back(nc);
for(vector<NodeConnection>::iterator it = newConnections.begin(); it != newConnections.end(); ++it)
{
cout << "Socket ID: " << it->fd << endl;
cout << "Their Address: " << it->ipstr << endl;
cout << "Their Port: " << it->port << endl;
cout << "My Size: " << newConnections.size() << endl;
cout << "**************\n";
//cout << "Their Port: " << (int)ntohs(it->theirAddress.sin_port) << endl;
}
exit(0);
}
// close(new_fd); // parent doesn't need this
}
}

基本上,每当我获得一个新连接时,我都想将该连接的详细信息存储到一个 vector 中。我决定通过将详细信息添加到 NodeConncetion 结构来做到这一点:

#include <sys/socket.h>
#include <arpa/inet.h>
struct NodeConnection
{
int fd;
socklen_t sin_size;
struct sockaddr_storage theirAddress;
char ipstr[INET6_ADDRSTRLEN];
int port;
};

这样,我的 Manager 对象就可以轮询这些连接以获取数据。

我遇到的问题是,一旦客户端连接,它就会打印出详细信息。当另一个连接时,它也会打印那个的详细信息;但是,它并没有像我预期的那样打印第一个连接,因为我执行了 .push_back(nc) 来保存新的 NodeConnection。

示例输出:

Hints set.
Binding Socket... Socket Bound!
server: waiting for connections...
server: got connection from 127.0.0.1
Socket ID: 4
Their Address: 127.0.0.1
Their Port: 33744
My Size: 1
**************
server: got connection from 127.0.0.1
Socket ID: 5
Their Address: 127.0.0.1
Their Port: 33745
My Size: 1
**************

我可能不完全理解如何保存关闭连接数据..所以如果我以错误的方式进行此操作,请告诉我。

最佳答案

在调用 fork() 之后,您正在将连接详细信息推送到子进程中的 vector。

fork() 创建一个全新的进程,它不与父进程共享任何内存。子项从父项的相同拷贝开始,但对子项中的变量所做的更改在父项中不可见,反之亦然。

所以你的顺序是:

  1. parent 接受连接并创建 child
  2. child 将连接数据添加到它的 vector (它是空的)
  3. child 打印 vector (现在包含一个条目)
  4. child 退出(并且它的 vector 拷贝现在消失了)
  5. 重复步骤 1 中的下一个连接。

如果要保留此连接数据,则需要将其添加到父进程中的 vector。

我注意到您将问题标记为“多线程”——这可能解释了混淆,因为您的程序不是多线程的,而是多进程的。同一进程中的多个线程确实共享内存。不过,我并不是建议您改为使用线程 - 这会带来一整套您可能不需要的其他问题。

关于c++ - 尝试保存与成员 vector 的连接 - 一次只保存一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22163249/

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