多个连接套接字c ++
Posted
技术标签:
【中文标题】多个连接套接字c ++【英文标题】:Multiple connections sockets c++ 【发布时间】:2018-01-01 21:19:01 【问题描述】:我正在尝试实现自己的服务器和客户端,它们使用套接字来发送和接收数据。但是我在实现多线程方面遇到了一些问题。 我的 server.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
using namespace std;
void connection_handler(int socket)
char client_message[256];
memset(&client_message, 0, 256);
size_t message_size = 0;
while ((message_size = recv(socket, client_message, sizeof(client_message) - 1, 0)) > 0)
client_message[message_size] = '\0';
cout << "[Server] Client message accepted" << endl;
cout << "[Server] Client message: " << client_message << endl;
if (write(socket, client_message, message_size) == -1)
cout << "[Client] Message sending failed" << endl;
return;
cout << "[Server] Message sent to client" << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
memset(&client_message, 0, 256);
int main()
unsigned short int PORT = 8080;
int listener, client_socket;
socklen_t client_len;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
listener = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
if (inet_aton("127.0.0.1", &server_address.sin_addr) == 0)
cout << "[Server] Invalid IP address" << endl;
return -1;
if (bind(listener, (struct sockaddr*) &server_address, sizeof(server_address)) == -1)
cout << "[Server] Binding failed" << endl;
return -1;
cout << "[Server] All setting are done" << endl;
cout << "[Server] Server enabled" << endl;
if (listen(listener, 100) == -1)
cout << "[Server] Listening failed" << endl;
return -1;
cout << "[Server] Waiting for connection..." << endl;
for (; ;)
client_socket = accept(listener, (struct sockaddr*) &server_address, &client_len);
cout << "[Server] Connection accepted" << endl << endl;
cout << "----------------------------" << endl << endl;
int new_socket = client_socket;
thread handling_thread(connection_handler, new_socket);
handling_thread.detach();
我的client.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
int main()
unsigned short int PORT = 8080;
int sockfd;
char buffer[256] = 0;
struct sockaddr_in server_address;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sockfd, (struct sockaddr*) &server_address, sizeof(server_address)) < 0)
cout << "[Client] Connection failed" << endl;
return -1;
cout << "[Client] All setting are done" << endl;
cout << "[Client] Succefully connected to server" << endl << endl;
cout << "----------------------------" << endl << endl;
while (true)
string client_request;
cout << "[Client] Enter a message: ";
getline(cin, client_request);
if (client_request == "-1")
write(sockfd, client_request.c_str(), client_request.size());
close(sockfd);
cout << endl << "[Client] Client exited" << endl;
return 0;
if (write(sockfd, client_request.c_str(), client_request.size()) == -1)
cout << "[Client] Message sending failed" << endl;
cout << "[Client] Message sent to server" << endl;
memset(&buffer, 0, 256);
read(sockfd, buffer, 256);
cout << "[Client] Server message: " << buffer << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
在我再创建一个与服务器的连接之后,它可以正常工作,然后第二个客户端可以发送和接收数据,但此时第一个客户端无法正常工作。
我像这样编译我的程序:g++ server.cpp -lpthread -o server -std=c++11
然后在其他控制台选项卡中运行我编译的 client.cpp:./client
。
为了检查多线程工作,我再次运行客户端(再次在另一个选项卡中)并尝试同时在两个选项卡中发送请求。
我想在我的程序中实现多线程。我该怎么做?
UPD:我正在使用 Linux
UPD2:问题已解决。修复了那里的代码。
【问题讨论】:
new_socket
是 for
循环的局部变量,因此线程持有的指针在线程使用它时将指向垃圾区,这真是太奇怪了。快速修复:按值传递,而不是作为指针传递。还要查看 select
、epoll
或重叠 IO,具体取决于您的目标操作系统。
如果 message_size = recv(*socket, client_message, 256, 0)
读取 256 个字节,可能不相关的 client_message[message_size] = '\0';
将刺穿 char client_message[256];
并具有未定义的行为。试试message_size = recv(*socket, client_message, sizeof(client_message)-1, 0)
吧。
@user4581301 哦,天哪.. 你的第一个提示对我有帮助,现在它工作得很好。非常感谢你:)
这里是一个使用 select 来处理只有一个线程的多个连接的示例:gnu.org/software/libc/manual/html_node/Server-Example.html
【参考方案1】:
int new_socket = client_socket;
thread handling_thread(connection_handler, &new_socket);
handling_thread.detach();
这将初始化new_socket
,它在此for循环内的本地范围内声明,然后将指向此new_socket
的指针传递给一个新线程,该线程开始启动并分离。紧接着,这个for
循环迭代结束,这会破坏new_socket
对象,然后再开始这个循环的下一次迭代。
同时,执行线程反复尝试取消引用它收到的int *
,它现在指向一个已销毁的对象。这会导致未定义的行为,并且可能是您的程序“不工作”的原因。
最简单的解决方案是在动态范围内创建int
套接字值,使用new
,然后将指向这个new
ed 套接字值的指针传递给执行线程。当然,执行线程将负责检索套接字值,然后正确地delete
ing 它,以避免内存泄漏。
这对于这个简单的程序应该足够了。为了可靠性,更复杂的程序可能需要稍微复杂的套接字和动态范围处理逻辑。
【讨论】:
哪种方式最好?在堆栈或堆中创建新套接字?现在我的程序运行良好,谢谢 在这种情况下,堆上是最简单的方法。它仍然可以完全在堆栈上完成(自动范围),但它需要一些工作 - 使用互斥锁和条件变量,父线程等待直到新线程将套接字值复制到自己的堆栈,然后发信号通知父线程继续。new
, delete
? - 为什么不简单地按值传递套接字整数? - 我想你已经想到了POSIX Threads C
接口,你不能(正确)将int
转换为void *
,以便人们使用分配/解除分配方法将指针传递给线程以上是关于多个连接套接字c ++的主要内容,如果未能解决你的问题,请参考以下文章