【发布时间】:2020-10-27 03:36:57
【问题描述】:
我想使用套接字编程远程运行服务器和客户端(来自我的电脑的客户端和远程主机上的服务器)。我用 C++ 编写了一个在本地机器上运行的程序,包括客户端和服务器。现在如何从不同的机器运行服务器?在 server.cpp 中,我使用了 INADDR_ANY,我不知道如何将我的 PC 的 IP 地址(在哪个服务器上运行)提供给客户端和 pc 的 IP 地址(我有我的客户端程序) ) 到服务器。客户端和服务器是否具有相同的端口号,或者它们也可以具有不同的端口号?如果是,那我该如何分配呢?
服务器.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();
}
【问题讨论】:
-
服务器不需要知道客户端的IP地址,它可以使用
IPADDR_ANY接受来自任何IP地址的连接。客户端需要知道服务器的 IP 地址。它如何进行,完全取决于你。没有法律规定客户端如何计算服务器的 IP 地址。无论您采用哪种方式,从硬编码的服务器地址到实施复杂的网络发现协议,都完全由您选择。并且服务器的端口与客户端的端口无关。其实connect()会选择一个随机端口默认。 -
你今天可能已经问过这个或类似的问题了吗? stackoverflow.com/questions/64523841/… 看起来非常相似。
-
...在作为重复文件关闭后。你不明白为什么要关闭重复项吗?不是你把问题删了再问!
-
当然客户端需要知道服务器的端口号。它怎么可能连接到服务器?
-
@SamVarshavchik,我希望服务器接受来自特定 IP 地址的连接。我怎样才能做到这一点?我应该在 server.cpp 中使用什么来代替 INADDR_ANY?
标签: c++ sockets tcp tcpclient socketserver