C++ Server 放入容器后不工作
C++ Server doesn't work after being put in a container
当 运行 正常连接我的服务器和客户端时,没有出现任何问题,所以我认为问题与 client/server 本身无关,但我会 post 无论如何。
RTCServer.cpp:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <pthread.h>
#include "Room.h"
using namespace std;
//TODO: figure out ptr situation
void* handleConnection(void* p_room) {
Room* room = (Room *)p_room;
int clientSocket = room->getNewest();
char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXSERV]; // port the client is connect on
memset(host, 0, NI_MAXHOST);
memset(service, 0, NI_MAXSERV);
// accept and echo message back to client
char buf[4096];
while (true) {
memset(buf, 0, 4096);
int bytesReceived = recv(clientSocket, buf, 4096, 0);
std::cout << "from client at " << clientSocket << "\n";
if (bytesReceived == -1) {
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (bytesReceived == 0) {
cout << "Client disconnected " << endl;
break;
}
cout << string(buf, 0, bytesReceived) << endl;
// Echo message back to all clients
std::vector<int> members = room->members();
for (int i = 0; i < room->size(); i++) {
send(members[i], buf, bytesReceived + 1, 0);
}
}
//?
close(clientSocket);
}
int main(int argc, char *argv[]) {
//Create a socket
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
cerr << "Can't create a socket! Quitting" << endl;
return -1;
}
// Bind the ip address and port to a socket
sockaddr_in sockInfo;
sockInfo.sin_family = AF_INET;
sockInfo.sin_port = htons(54000);
inet_pton(AF_INET, "127.0.0.1", &sockInfo.sin_addr);
bind(serverSocket, (sockaddr*)&sockInfo, sizeof(sockInfo));
listen(serverSocket, SOMAXCONN);
// Wait for a connection
// Create new thread and handle
Room room;
while(1) {
sockaddr_in client;
socklen_t clientSize = sizeof(client);
int clientSocket = accept(serverSocket, (sockaddr*)&client, &clientSize);
std::cout << clientSocket << "\n";
room.addMember(clientSocket);
pthread_t thread;
pthread_create(&thread, NULL, handleConnection, &room);
}
return 0;
}
RTCClient.cpp:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <pthread.h>
using namespace std;
void* toServer(void* info) {
pair<string, int>* pairPtr = (pair<string,int>*)info;
string username = pairPtr->first;
int sock = pairPtr->second;
char buf[4096];
string userInput;
while(1) {
cout << "> ";
getline(cin, userInput);
//Send to server
string msg = username + " :: " + userInput;
int sendRes = send(sock, msg.c_str(), msg.size() + 1, 0);
if (sendRes == -1) {
cout << "Could not send to server!\n";
continue;
}
}
return NULL;
}
void* fromServer(void* info) {
int sock = *(int *)info;
char buf[4096];
while(1) {
memset(buf, 0, 4096);
std::cout << "about to recv" << "\n";
int bytesReceived = recv(sock, buf, 4096, 0);
if (bytesReceived == -1) {
cout << "There was an error getting a response from server\n";
}
//Display response
else {
cout << string(buf, bytesReceived) << "\n";
}
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cout << "use format ./client <username>\n";
return 1;
}
string username = argv[1];
//Create a socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
return 1;
}
//Create a hint structure for the server we're connecting with
int port = 54000;
string ipAddress = "127.0.0.1";
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
//Connect to the server on the socket
int connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));
std::cout << "connected" << "\n";
if (connectRes == -1) {
return 1;
}
pair<string, int> pairPtr = {username, sock};
pthread_t toServerThread;
pthread_create(&toServerThread, NULL, toServer, &pairPtr);
pthread_t fromServerThread;
pthread_create(&fromServerThread, NULL, fromServer, &sock);
while (1) {}
//Close the socket
close(sock);
return 0;
}
我用g++ *.cpp -lpthread -o <name>
编译
到目前为止,我的 Dockerfile 很简单,我只想在继续之前将服务器 运行 放入容器中。
Docker 文件:
FROM ubuntu:latest
COPY server /
ENTRYPOINT ["./server"]
然后我构建图像:
docker build -t chatserver .
要运行我做的图片:
docker run -d -p 54000:80 --name chatserver chatserver
执行客户端后,没有建立实际连接,项目的功能也消失了。我怀疑我的问题与客户端和服务器端口的暴露方式有关。
您正在将 docker 容器中的端口映射到 80 - 因此要么更改您的服务器代码以绑定到端口 80,要么使用 docker ... -p 54000:54000 ...
实用提示:
在你的 devcontainer.json
添加
"appPort":["54000:54000/tcp"],
(否则使用 udp,我使用 VSCode)
当 运行 正常连接我的服务器和客户端时,没有出现任何问题,所以我认为问题与 client/server 本身无关,但我会 post 无论如何。
RTCServer.cpp:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <pthread.h>
#include "Room.h"
using namespace std;
//TODO: figure out ptr situation
void* handleConnection(void* p_room) {
Room* room = (Room *)p_room;
int clientSocket = room->getNewest();
char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXSERV]; // port the client is connect on
memset(host, 0, NI_MAXHOST);
memset(service, 0, NI_MAXSERV);
// accept and echo message back to client
char buf[4096];
while (true) {
memset(buf, 0, 4096);
int bytesReceived = recv(clientSocket, buf, 4096, 0);
std::cout << "from client at " << clientSocket << "\n";
if (bytesReceived == -1) {
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (bytesReceived == 0) {
cout << "Client disconnected " << endl;
break;
}
cout << string(buf, 0, bytesReceived) << endl;
// Echo message back to all clients
std::vector<int> members = room->members();
for (int i = 0; i < room->size(); i++) {
send(members[i], buf, bytesReceived + 1, 0);
}
}
//?
close(clientSocket);
}
int main(int argc, char *argv[]) {
//Create a socket
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
cerr << "Can't create a socket! Quitting" << endl;
return -1;
}
// Bind the ip address and port to a socket
sockaddr_in sockInfo;
sockInfo.sin_family = AF_INET;
sockInfo.sin_port = htons(54000);
inet_pton(AF_INET, "127.0.0.1", &sockInfo.sin_addr);
bind(serverSocket, (sockaddr*)&sockInfo, sizeof(sockInfo));
listen(serverSocket, SOMAXCONN);
// Wait for a connection
// Create new thread and handle
Room room;
while(1) {
sockaddr_in client;
socklen_t clientSize = sizeof(client);
int clientSocket = accept(serverSocket, (sockaddr*)&client, &clientSize);
std::cout << clientSocket << "\n";
room.addMember(clientSocket);
pthread_t thread;
pthread_create(&thread, NULL, handleConnection, &room);
}
return 0;
}
RTCClient.cpp:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <pthread.h>
using namespace std;
void* toServer(void* info) {
pair<string, int>* pairPtr = (pair<string,int>*)info;
string username = pairPtr->first;
int sock = pairPtr->second;
char buf[4096];
string userInput;
while(1) {
cout << "> ";
getline(cin, userInput);
//Send to server
string msg = username + " :: " + userInput;
int sendRes = send(sock, msg.c_str(), msg.size() + 1, 0);
if (sendRes == -1) {
cout << "Could not send to server!\n";
continue;
}
}
return NULL;
}
void* fromServer(void* info) {
int sock = *(int *)info;
char buf[4096];
while(1) {
memset(buf, 0, 4096);
std::cout << "about to recv" << "\n";
int bytesReceived = recv(sock, buf, 4096, 0);
if (bytesReceived == -1) {
cout << "There was an error getting a response from server\n";
}
//Display response
else {
cout << string(buf, bytesReceived) << "\n";
}
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cout << "use format ./client <username>\n";
return 1;
}
string username = argv[1];
//Create a socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
return 1;
}
//Create a hint structure for the server we're connecting with
int port = 54000;
string ipAddress = "127.0.0.1";
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
//Connect to the server on the socket
int connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));
std::cout << "connected" << "\n";
if (connectRes == -1) {
return 1;
}
pair<string, int> pairPtr = {username, sock};
pthread_t toServerThread;
pthread_create(&toServerThread, NULL, toServer, &pairPtr);
pthread_t fromServerThread;
pthread_create(&fromServerThread, NULL, fromServer, &sock);
while (1) {}
//Close the socket
close(sock);
return 0;
}
我用g++ *.cpp -lpthread -o <name>
编译
到目前为止,我的 Dockerfile 很简单,我只想在继续之前将服务器 运行 放入容器中。
Docker 文件:
FROM ubuntu:latest
COPY server /
ENTRYPOINT ["./server"]
然后我构建图像:
docker build -t chatserver .
要运行我做的图片:
docker run -d -p 54000:80 --name chatserver chatserver
执行客户端后,没有建立实际连接,项目的功能也消失了。我怀疑我的问题与客户端和服务器端口的暴露方式有关。
您正在将 docker 容器中的端口映射到 80 - 因此要么更改您的服务器代码以绑定到端口 80,要么使用 docker ... -p 54000:54000 ...
实用提示: 在你的 devcontainer.json 添加
"appPort":["54000:54000/tcp"],
(否则使用 udp,我使用 VSCode)