在 C++ 中使用 TCP 套接字进行远程客户端和服务器通信
Remote client and server communication using TCP sockets in c++
我想 运行 服务器和客户端使用远程套接字编程(来自我的电脑的客户端和远程主机上的服务器)。我用 C++ 编写了一个程序,它在本地机器上 运行s,包括客户端和服务器。现在我如何 运行 来自不同机器的服务器?在 server.cpp 中,我使用了 INADDR_ANY,我不知道如何将我的 PC(在哪个服务器上 运行ning)的 IP 地址提供给客户端和 ip 地址个人电脑(我有我的客户端程序)到服务器。客户端和服务器是否具有相同的端口号,或者它们也可以具有不同的端口号?如果是,那我该如何分配?
server.cpp
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#include <cstdlib>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
WSADATA data;
WORD ver = MAKEWORD(2, 2);
int wres = WSAStartup(ver, &data);
if (wres != 0)
{
cerr << "unable to initialize winsock" << endl;
return;
}
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "unable to create a socket" << endl;
return;
}
sockaddr_in sdata;
sdata.sin_family = AF_INET;
sdata.sin_port = htons(54000);
sdata.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listening, (sockaddr*)&sdata, sizeof(sdata));
listen(listening, SOMAXCONN);
sockaddr_in client;
int csize = sizeof(client);
SOCKET clientsock = accept(listening, (sockaddr*)&client, &csize);
char host[NI_MAXHOST];
char service[NI_MAXSERV];
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
}
//listening
closesocket(listening);
char buf[4096];
//char temp[] = "Hello";
//char *input = temp;
string input;
int inputsize;
while (true)
{
ZeroMemory(buf, 4096);
int recbyte = recv(clientsock, buf, 4096, 0);
if (recbyte == SOCKET_ERROR)
{
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (recbyte == 0)
{
cout << "Client disconnected " << endl;
break;
}
cout << "Client>";
cout << string(buf, 0, recbyte) << endl;
cout << "> ";
getline(cin, input);
send(clientsock, input.c_str(), input.size() + 1, 0);
}
closesocket(clientsock);
WSACleanup();
system("pause");
}
client.cpp
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
void main()
{
string ipAddress = "127.0.0.1";
int port = 54000;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
cerr << "Can't start Winsock, Err #" << wsResult << endl;
return;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
WSACleanup();
return;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR)
{
cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
closesocket(sock);
WSACleanup();
return;
}
char buf[4096];
string userInput;
do
{
cout << "> ";
getline(cin, userInput);
if (userInput.size() > 0)
{
int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0);
if (sendResult != SOCKET_ERROR)
{
ZeroMemory(buf, 4096);
int bytesReceived = recv(sock, buf, 4096, 0);
if (bytesReceived > 0)
{
cout << "SERVER> " << string(buf, 0, bytesReceived) << endl;
}
}
}
} while (userInput.size() > 0);
closesocket(sock);
WSACleanup();
}
我认为您没有完全理解 client-server 的作用。
服务器不知道、不能也不应该知道连接到它的客户端的地址(尽管它可以在连接后知道)。
要完成连接,客户端需要知道它们应该连接到的 IP 和端口,并且服务器应该将其服务器端口(它侦听的端口)绑定到正确的 IP 和端口。
默认 IP 通常使用 INADDR_ANY 表示,在大多数情况下这是可以的,但是如果机器上有多个地址,您可能必须指定另一个地址。
客户端通常不绑定它们的连接套接字,因为它们自己的端口号并不重要。他们自己的 IP 也不重要,因为在连接期间不使用它。
因此,您应该做的是 运行 在您的 PC 上安装您的服务器应用程序,并将您的 PC 地址和端口号提供给所有寻求连接到您的客户端。
我想 运行 服务器和客户端使用远程套接字编程(来自我的电脑的客户端和远程主机上的服务器)。我用 C++ 编写了一个程序,它在本地机器上 运行s,包括客户端和服务器。现在我如何 运行 来自不同机器的服务器?在 server.cpp 中,我使用了 INADDR_ANY,我不知道如何将我的 PC(在哪个服务器上 运行ning)的 IP 地址提供给客户端和 ip 地址个人电脑(我有我的客户端程序)到服务器。客户端和服务器是否具有相同的端口号,或者它们也可以具有不同的端口号?如果是,那我该如何分配?
server.cpp
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#include <cstdlib>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
WSADATA data;
WORD ver = MAKEWORD(2, 2);
int wres = WSAStartup(ver, &data);
if (wres != 0)
{
cerr << "unable to initialize winsock" << endl;
return;
}
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "unable to create a socket" << endl;
return;
}
sockaddr_in sdata;
sdata.sin_family = AF_INET;
sdata.sin_port = htons(54000);
sdata.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listening, (sockaddr*)&sdata, sizeof(sdata));
listen(listening, SOMAXCONN);
sockaddr_in client;
int csize = sizeof(client);
SOCKET clientsock = accept(listening, (sockaddr*)&client, &csize);
char host[NI_MAXHOST];
char service[NI_MAXSERV];
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
}
//listening
closesocket(listening);
char buf[4096];
//char temp[] = "Hello";
//char *input = temp;
string input;
int inputsize;
while (true)
{
ZeroMemory(buf, 4096);
int recbyte = recv(clientsock, buf, 4096, 0);
if (recbyte == SOCKET_ERROR)
{
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (recbyte == 0)
{
cout << "Client disconnected " << endl;
break;
}
cout << "Client>";
cout << string(buf, 0, recbyte) << endl;
cout << "> ";
getline(cin, input);
send(clientsock, input.c_str(), input.size() + 1, 0);
}
closesocket(clientsock);
WSACleanup();
system("pause");
}
client.cpp
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
void main()
{
string ipAddress = "127.0.0.1";
int port = 54000;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
cerr << "Can't start Winsock, Err #" << wsResult << endl;
return;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
WSACleanup();
return;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR)
{
cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
closesocket(sock);
WSACleanup();
return;
}
char buf[4096];
string userInput;
do
{
cout << "> ";
getline(cin, userInput);
if (userInput.size() > 0)
{
int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0);
if (sendResult != SOCKET_ERROR)
{
ZeroMemory(buf, 4096);
int bytesReceived = recv(sock, buf, 4096, 0);
if (bytesReceived > 0)
{
cout << "SERVER> " << string(buf, 0, bytesReceived) << endl;
}
}
}
} while (userInput.size() > 0);
closesocket(sock);
WSACleanup();
}
我认为您没有完全理解 client-server 的作用。 服务器不知道、不能也不应该知道连接到它的客户端的地址(尽管它可以在连接后知道)。 要完成连接,客户端需要知道它们应该连接到的 IP 和端口,并且服务器应该将其服务器端口(它侦听的端口)绑定到正确的 IP 和端口。 默认 IP 通常使用 INADDR_ANY 表示,在大多数情况下这是可以的,但是如果机器上有多个地址,您可能必须指定另一个地址。 客户端通常不绑定它们的连接套接字,因为它们自己的端口号并不重要。他们自己的 IP 也不重要,因为在连接期间不使用它。 因此,您应该做的是 运行 在您的 PC 上安装您的服务器应用程序,并将您的 PC 地址和端口号提供给所有寻求连接到您的客户端。