【问题标题】:WinSock program in C, works only on local computerC语言中的WinSock程序,仅适用于本地计算机
【发布时间】:2014-01-14 10:38:38
【问题描述】:

我是网络编程的新手,开始学习如何在 C 中使用 WinSock。

我现在对网络一无所知。

无论如何,我已经使用 WinSock 为客户端和服务器编写了以下代码。

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define MY_ERROR 1
#define PORT 7777
#define MAX_NUM_CLIENTS 1 /* I don't know how to thread right now. */
#define MAX_CLIENT_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket, acceptSocket;
struct sockaddr_in server, client;
int sockAddrInLength = sizeof(struct sockaddr_in);
char clientMessage[MAX_CLIENT_MSG_LEN];
int clientMessageLength;
char* message;

int running = 1;

if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
    fprintf(stderr, "WSAStartup failed.\n");
    return MY_ERROR;
}
printf("WSAStartup succeded.\n");

mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
    fprintf(stderr, "Socket creation failed.\n");
    return MY_ERROR;
}
printf("Socket creation succeeded.\n");

server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);

if (bind(mySocket, (struct sockaddr*) &server, sizeof server) == SOCKET_ERROR)
{
    fprintf(stderr, "Binding socket on port %d failed.\n", PORT);
    return MY_ERROR;
}
printf("Binding socket on port %d successfully.\n", PORT);

while (running)
{
        listen(mySocket, MAX_NUM_CLIENTS);
        printf("Waiting for a connection...\n");

        acceptSocket = accept(mySocket, (struct sockaddr*) &client, &sockAddrInLength);
        if (acceptSocket == INVALID_SOCKET)
        {
            fprintf(stderr, "Accept failed.\n");
            return MY_ERROR;
        }
        printf("Accept succeeded.\n");

        if ((clientMessageLength = recv(acceptSocket, clientMessage, sizeof clientMessage, 0)) == SOCKET_ERROR)
        {
            fprintf(stderr, "Recv failed.\n");
            return MY_ERROR;
        }
        printf("Recv succeeded.\n");

        printf("Data:\n");
        clientMessage[clientMessageLength] = NULL; /* Null terminator */
        printf("Client: %s\n", clientMessage);

        message = "Hello client, I'm the server. Bye bye. :-)\n";
        if (send(acceptSocket, message, strlen(message), 0) < 0)
        {
            fprintf(stderr, "Send failed.\n");
            return MY_ERROR;
        }
        printf("Send succeded.\n");
}
closesocket(mySocket);
WSACleanup();
getchar();
return 0;

}

这是客户端的代码:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>


#define IP /* My IP */
#define MY_ERROR 1
#define PORT 7777
#define MAX_SERVER_MSG_LEN 1000

int main()
{
WSADATA wsa;
SOCKET mySocket;
struct sockaddr_in server;
char* message;
char serverMessage[MAX_SERVER_MSG_LEN];
int serverMessageLength;

if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
    fprintf(stderr, "WSAStartup failed.\n");
    getchar();
    return MY_ERROR;
}
printf("WSASucceeded.\n");

mySocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

if (mySocket == INVALID_SOCKET)
{
    fprintf(stderr, "Socket creation failed.\n");
    getchar();
    return MY_ERROR;
}

server.sin_addr.s_addr = inet_addr(IP);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);

if (connect(mySocket, (struct sockaddr*) &server, sizeof server) < 0)
{
    fprintf(stderr, "Connection failed. error: %s\n",WSAGetLastError());
    getchar();
    return MY_ERROR;
}
printf("Connection established.\n");

message = "Hello server, I'm the sweet client. :-)\n";
if (send(mySocket, message, strlen(message), 0) < 0)
{
    fprintf(stderr, "Sending failed.\n");
    return MY_ERROR;
}
printf("Sending succeeded.\n");

if ((serverMessageLength = recv(mySocket, serverMessage, sizeof serverMessage, 0)) == SOCKET_ERROR)
{
    fprintf(stderr, "Recv failed.\n");
    return MY_ERROR;
}
printf("Recv succeeded.\n");

printf("Data:\n");
serverMessage[serverMessageLength] = NULL;
printf("Server: %s", serverMessage);

closesocket(mySocket);
getchar();
return 0;

}

好的。

当我在我的计算机上同时运行服务器和客户端,并将 IP(在客户端代码中)定义为我的内部 IP(我认为,因为它是 192.168.x.x 的形式)时,它工作正常。

当我将 IP 定义为我的外部 IP 时,它在我的计算机上不起作用(当我在我的计算机上运行这两个程序时)。连接失败。

此外—— 当我尝试在任何其他计算机上运行客户端时,它不起作用(当 IP 定义为我的内部或外部 IP 时),连接失败。

我的问题是:

  1. 为什么当我在我的计算机上同时运行服务器和客户端时,它只能使用我的内部 IP?

  2. 我应该怎么做才能使客户端可以在另一台计算机上运行并且可以正常工作?

  3. 我知道答案可能包含“内部/外部 IP”、“路由器”、“防火墙”或“端口转发”等术语。 请记住,我真的是网络方面的新手,我对这些术语一无所知,所以请:我希望您的解释对初学者友好。 我想开始学习网络,但我的第一步是了解如何使用套接字,我在与其他计算机的连接中遇到了问题。

如果您有任何文章/类似的东西,以便让我更好地了解问题,它也会有所帮助。

非常感谢! :)

【问题讨论】:

  • “它不起作用”不是一个有用的问题描述。
  • 您能否发布您尝试从另一台计算机连接到服务器时遇到的错误?
  • @DavidSchwartz 抱歉,我只是没有足够的网络知识来更好地解释它。连接失败(我在客户端输入“if”语句并打印“连接失败”。
  • @demo.b 它打印“连接失败”(我在客户端代码中输入 if 语句)。
  • 确保服务器上的防火墙没有阻止传入数据。看看telnet &lt;serverIP&gt; 7777 做了什么。

标签: c sockets networking network-programming winsock2


【解决方案1】:

这看起来不像是编码问题,而是网络配置问题。

让我试着改一下你的意思:如果我误解了,请纠正我:-

  • 您有一个“内部”网络 (192.168.x.y)。
  • 您在内部网络的一台 PC 上运行客户端,而在另一台 PC 上运行服务器。
  • 到目前为止一切正常。

但是,您也通过不同的“外部”IP 地址连接到互联网 - 当您的客户端尝试通过此地址访问服务器时,它会失败。 (WSAGetLastError 的确切错误代码在这里很有用,拜托)

此时,这取决于您连接到网络的方式。让我们假设一个典型的家庭办公室场景。您有宽带,ADSL 路由器/调制解调器为您提供网络连接。现在,虽然路由器将有一个“外部”IP 地址,但您本地网络上的 PC 通常没有。因此,如果您尝试连接到“外部”IP,您实际上是在尝试与路由器通信。

这就是Port forwarding 发挥作用的地方。您需要将路由器配置为将端口 7777 转发到内部网络上服务器的正确 IP 地址。你会在路由器的某个地方找到这样的屏幕。

您将为“from”和“to”输入端口 7777,启用 TCP,并指定服务器的 LAN 地址。然后路由器会将端口 7777 上的传入连接转发到指定的服务器。

【讨论】:

  • 非常感谢!它有效:) 正是我正在寻找的答案。
猜你喜欢
  • 1970-01-01
  • 2011-06-10
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
  • 2013-03-16
相关资源
最近更新 更多