【发布时间】:2022-01-24 08:59:33
【问题描述】:
我正在做一个简单的发送/接收,为了在线程中执行每个请求,我设置了我的处理函数,如下所示:
更新:使用 std::thread 并在使用后正确关闭套接字。我没有使用循环来读取 atm,因为我只是发送远低于 1024 缓冲区限制的小测试消息。不幸的是,我仍然收到奇怪的 ip 和端口数据。
int P2PServer::socketReceiveHandler(int s) {
struct sockaddr_in *sin = (struct sockaddr_in *)&s;
char buffer[1024] = {0};
int reader;
reader = read(s, buffer, 1024);
if (reader <= 0) {
return 0;
} else {
std::cout << reader << std::endl; // let's see
}
char ip[INET_ADDRSTRLEN];
int port=0;
inet_ntop(AF_INET, &(sin->sin_addr), ip, sizeof(ip));
port = htons(sin->sin_port);
strcpy(ip, inet_ntoa(sin->sin_addr));
printf ("Connection from %s:%d\n", ip, port);
printf("Connection from: %d.%d.%d.%d", buffer[197], buffer[198], buffer[199], buffer[200]);
//int port = 0; // Start with zero
port |= buffer[204] & 0xFF; // Assign first byte to port using bitwise or.
port <<= 8; // Shift the bits left by 8
port |= buffer[205] & 0xFF; // (so the byte from before is on the correct position)
printf(" Port: %d\n\n", port);
char const* message = "I am an amazing server!";
std::cout << "received: " << buffer << std::endl;
send(s, message, strlen(message) , 0 );
printf("Server : Message has been sent ! \n");
if (close(s) == -1) {
p2putils::logit("Close problems");
std::cout << "errno: " << errno << std::endl;
}
return 0;
}
函数调用如下:
std::thread peerThread (&P2PServer::socketReceiveHandler,this, incomingSocket);
peerThread.join();
这是服务器的输出:
./p2pserver 127.0.0.1 10001
Node usage for peers: ./p2pserver <ip> <port> <masternode>
If this is not the master node, restart with 3rd parameter
P2P Server: 127.0.0.1 is listening on PORT: 10001
Waiting for incoming connections...
23
Connection from 8.233.176.178:0
Connection from: 0.0.0.0 Port: 0
received: I am an amazing client.
Server : Message has been sent !
Waiting for incoming connections...
这是客户端的输出:
./p2pserver 127.0.0.1 10002 127.0.0.1
P2P Server: 127.0.0.1 is listening on PORT: 10002
Client : Message has been sent !
I am an amazing server!
Waiting for incoming connections...
【问题讨论】:
-
你为什么不用
std::thread?这将使使用非静态成员函数更容易(真的很简单)。而且您不必担心通过将指针传递给套接字描述符可能会发生的数据竞争,就像std::thread一样,您可以按值传递参数。 -
关于传输和套接字处理。您确实需要为
read调用添加错误检查。它可能会失败,也可能会返回0以指示连接已关闭。如果它是 TCP 套接字,则无法保证单个read调用实际上会接收到所有内容,您需要使用循环才能读取完整消息(并具有具有消息边界的协议)。 -
另外,一旦你完成了套接字,谁负责
close?您是否在显示的线程之外使用套接字?这是一场数据竞赛。如果你不close套接字,你就有资源泄漏。 -
@Someprogrammerdude 这是一场数据竞赛套接字不是线程安全的吗?
-
致 OP (Sonny Parlin):检查
read返回的内容!我敢打赌它返回的值小于197。
标签: c++ sockets network-programming p2p