winsock2套接字连接可以在本地电脑上使用,但不能从远程电脑上使用

问题描述 投票:0回答:1

我正在尝试学习c语言中的低级网络,并且已经学会了使用winsock制作、绑定、连接、接受等套接字的TCP客户端和服务器程序。

它们工作得很好,当两个程序在同一台计算机上运行时,我的简单聊天控制台可以按预期工作,但通过我的本地网络或另一个网络从另一台电脑上的客户端连接时,无法通过套接字连接进行通信。

这是我的服务器:

#include "sockets.h"

int main(){

    // SETUP AND BIND SERVER SOCKET

    SOCKET server_socket = socket_setup();
    SOCKADDR_IN address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("192.168.xx.xxx"); //using public IP, not local (127.0.0.1)
    address.sin_port = htons(6502);

    if(bind(server_socket, (SOCKADDR*)&address, sizeof(address)) == SOCKET_ERROR)
        WSA_ERR("Socket Bind Error");

    if(listen(server_socket, 5) == SOCKET_ERROR)
        WSA_ERR("Listening Error");

    SOCKET accept_socket = SOCKET_ERROR;
    do{
        accept_socket = accept(server_socket, NULL, NULL);
    }
    while(accept_socket == SOCKET_ERROR);

    // SEND AND RECEIVE BYTES

    char sendmsg[100] = "Hello Client";
    char recvmsg[100] = "";

    int bytes_sent = send(accept_socket, sendmsg, strlen(sendmsg), 0);
    if(bytes_sent == SOCKET_ERROR){
        WSA_ERR("Send Error");
    }else{
        printf("Send OK\n");
        printf("Bytes Sent: %ld\n", bytes_sent);
        printf("%s\n", sendmsg);
    }

    int bytes_rcvd = blocking_recv(accept_socket, recvmsg);
    if(bytes_rcvd == SOCKET_ERROR){
        WSA_ERR("Recv Error");
    }else{
        printf("Recv OK\n");
        printf("Bytes Rcvd: %ld\n", bytes_rcvd);
        printf("%s\n", recvmsg);
    }

    chat_loop(recvmsg, sendmsg, accept_socket);
    return 0;
}

和客户:

#include "sockets.h"

int main(){

    // SETUP AND CONNECT CLIENT SOCKET

    SOCKET client_socket = socket_setup();
    SOCKADDR_IN address;
    address.sin_family = AF_INET;
    printf("Enter IP address:\n");
    char ip[15];
    gets_s(ip, 15);
    address.sin_addr.s_addr = inet_addr(ip);
    address.sin_port = htons(6502);

    if(connect(client_socket, (SOCKADDR*)&address, sizeof(address)) == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK){
        WSA_ERR("Connection Error");
    }

    // SEND AND RECIEVE BYTES

    char sendmsg[100] = "Hello Server";
    char recvmsg[100] = "";

    int bytes_rcvd = blocking_recv(client_socket, recvmsg);
    if(bytes_rcvd == SOCKET_ERROR){
        WSA_ERR("Recv Error"); //<-- WSAGetLastError() from inside macro gives error 10057 here
    }else{
        printf("Recv OK\n");
        printf("Bytes Rcvd: %ld\n", bytes_rcvd);
        printf("%s\n", recvmsg);
    }

    int bytes_sent = send(client_socket, sendmsg, strlen(sendmsg), 0);
    if(bytes_sent == SOCKET_ERROR){
        WSA_ERR("Send Error");
    }else{
        printf("Send OK\n");
        printf("Bytes Sent: %ld\n", bytes_sent);
        printf("%s\n", sendmsg);
    }

    chat_loop(recvmsg, sendmsg, client_socket);

    system("pause");
    return 0;
}

此函数是“sockets.h”的一部分:

int blocking_recv(SOCKET sock, char buf[]){
    int result = 0;
    do{
        result = recv(sock, buf, 100, 0);
    }while(result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK);
    return result;
}

如果需要,我可以详细说明排除的代码和宏,但我认为问题一定出在此处,因为除了实际连接之外,一切都工作正常。

我已经禁用了所有防火墙、转发端口等。 我正在使用非阻塞套接字。

c windows sockets networking winsock2
1个回答
0
投票

服务器需要

bind()
属于运行服务器的计算机的本地 IP。否则,您可以将服务器
bind()
改为
INADDR_ANY
(
0.0.0.0
) 来绑定到计算机上的所有本地 IP。

客户端可以

connect()
连接到服务器绑定并侦听的任何IP:

  • 如果客户端和服务器运行在同一台机器上,则可以使用任何本地IP,或者

    INADDR_LOOPBACK
    127.0.0.1
    )。

  • 如果客户端和服务器在同一 LAN 网络上运行,则

    bind
    服务器到机器的 LAN IP 或
    INADDR_ANY
    ,然后
    connect()
    客户端到服务器的 LAN IP。

  • 如果客户端和服务器运行在不同的网络上,则客户端需要

    connect()
    到属于服务器网络的公共WAN IP,并且服务器网络上的路由器必须配置为启用端口转发才能通过从 WAN 到运行服务器的 LAN 计算机的传入连接。根据路由器的配置,其端口转发规则可以可以通过 uPNP 协议直接从服务器代码动态配置,否则规则必须由网络管理员手动配置。

© www.soinside.com 2019 - 2024. All rights reserved.