【问题标题】:Connecting to local virtual machine连接本地虚拟机
【发布时间】:2018-03-28 15:10:28
【问题描述】:

我怀疑这有一个我忽略的简单解决方案,可能与客户端或设置方式有关。
无论如何,我正在尝试建立一个简单的 Echo 服务器/客户端来了解套接字编程的基础知识。我有一台运行 Linux Mint 的虚拟机,主机运行的是 Windows 10。我设置的虚拟机运行服务器 c 代码,Windows 将运行客户端。

我开始制作服务器代码

//Echo Server for UNIX:  Using socket programming in C, a client sends a string
//to this server, and the server responds with the same string sent back to the client

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

int main()
{
    char stringBuffer[50]; //string buffer for reading incoming and resending
    int listener, communicator, c; //store values returned by socket system call 

    if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) //creates a new socket
        puts("Could not create socket");
    puts("Socket Created");

    struct sockaddr_in servAddr, client; //structure from <netinet/in.h> for address of server
    servAddr.sin_family = AF_INET; //addressing scheme set to IP
    servAddr.sin_port = htons(8888); //server listens to port 5000
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //symbolic constant of server IP address

    //binds the socket to the address of the current host and port# the server will run on
    if (bind(listener, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
        puts("Bind failed");
        return 1;
    }
    puts("Bind Successful");

    listen(listener, 5); //listens for up to 5 connections at a time
    c = sizeof(struct sockaddr_in);
    if ((communicator = accept(listener, (struct sockaddr*)&client, (socklen_t*)&c ))<0)
        puts("accept failed");
    puts("Connection Accepted");
    //wait until someone wants to connect, then whatever is sent can be read from communicator, which can then be sent back

    while(1){
        bzero(stringBuffer, 50); //sets buffer to 0
        read(communicator, stringBuffer, 50); //reads from communicator into buffer
        write(communicator, stringBuffer, strlen(stringBuffer)+1); //returns back
    }
    return 0;
}

之后,我通过在访客机器中打开另一个终端并输入“telnet localhost 8888”并输入我想要的任何字符串来对其进行测试。

这个测试现在可以工作了,在我的 Windows 机器上创建套接字编程的客户端:

#include <winsock.h>
#include <stdio.h>
#include <string.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library

int main(int argc, char *argv[])
{

    WSADATA wsadata; //variable for using sockets in windows
    SOCKET sock; //socket variable for network commands
    char sendString[50], recieveString[50]; //variables for sending and recieving messages to/from server

    //check if WSA initialises correctly
    if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
        printf("Error Code: %d", WSAGetLastError());

     //creates new socket and saves into sock
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
        printf("Could not create socket: %d", WSAGetLastError());
    printf("Socket created\n");

    struct sockaddr_in servAddr;
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //sets the IP address to the same machine as the server
    servAddr.sin_family = AF_INET; //addressing scheme set to TCP/IP
    servAddr.sin_port = htons(8888); //server address is on port 8888

    //connects to device with specifications from servAddr
    if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
        printf("Connection Error %d\n", WSAGetLastError());
        return 1;
    }
    printf("Connection Accepted\n");

    while(1){
        fgets(sendString, 50, stdin); //uses stdin to get input to put into sendString
        //sends sendString to server using sock's properties
        if (send(sock, sendString, strlen(sendString) + 1, 0) < 0); {
            printf("Send Failed");
            return 0;
        }

        //reads from server into recieveString
        if ((recv(sock, recieveString, 50, 0)) == SOCKET_ERROR)
            printf("Recieve Failed");
        printf("%s", recieveString); //prints out recieveString
    }
}

现在,在服务器仍在运行的情况下,当我尝试客户端时,我收到响应“连接错误”(来自第 35 行)。在查看了 Unix 和 WinSock 示例后,我不确定为什么连接会失败。我怀疑这可能与 windows 到 linux 虚拟机有关,但我不确定。

---更新--- 更新了意外分号并添加了 WSAGetLastError,它显示错误代码 10061;这转化为 “拒绝连接。 由于目标计算机主动拒绝,无法建立连接。这通常是由于尝试连接到在外部主机上处于非活动状态的服务——即没有运行服务器应用程序的服务。”

【问题讨论】:

  • 为什么if语句后面有分号?第 34 行
  • c 应该是 socklen_t 不是 int!
  • 你的正在在同一个盒子上运行服务器和客户端,不是吗?
  • @alk 你在说什么?是的,windows10 和 vmware linux mint 在同一台机器上(我唯一的电脑)

标签: c linux windows sockets virtual-machine


【解决方案1】:

[第三次编辑后:]

抱歉,请重新阅读您的问题。重要的是这里:

我设置的虚拟机运行服务器 c 代码,Windows 将运行客户端。

127.0.0.1 是一个始终仅限本地到启用 IP 的框的地址。因此,您的服务器正在侦听 Linux VM 本地的接口 127.0.0.1,并且客户端尝试连接到 Windows 机器本地的 127.0.0.0。这两个接口相同。结果很明显,即客户端找不到任何要连接的东西。

127.0.0.1(所谓的“IPv4 本地环回接口e”)只能用于本地一个框的连接.

【讨论】:

  • 好吧,这回答了为什么,问题是我用什么IP来做这个?
  • 服务器主机的,err,IP?
  • 也就是说,我也尝试过使用INADDR_ANY作为服务器,但是客户端发送到哪个IP? ——编辑:好吧,那么他们真的将彼此视为网络上完全不同的事物吗?我不确定 IP 地址如何真正适用于访客机器,抱歉
  • 您必须找出服务器主机的 IP 地址。没有人能为你做到这一点。服务器程序当然应该将自己绑定到 INADDR_ANY,但这只是解决方案的一半。
  • linux命令:ip addr show显示可用的ip地址。
【解决方案2】:
if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0); {
    printf("Connection Error");
    return 1;
}

这只是一个微不足道的语法错误。您正在无条件地进入区块。删除第一个分号。

但是,还有更重要的一点需要说明。当您从诸如connect() 之类的系统调用中得到错误时,您必须打印错误。不仅仅是你自己设计的一些信息。否则你不知道你是否只是有一个错误,或者一个暂时的问题,或者一个长期存在的问题,还是一个永久性的问题。

printf() 更改为:

printf("Connect error %s\n", WSAGetLastError());

然后不要继续,就好像错误没有发生一样。

请注意,这适用于所有系统调用,具体包括socket()bind()listen()connect()accept()recv()send() 和朋友。

【讨论】:

  • 对不起,我忽略了分号,但这确实不是问题。不知道为什么我忘记了那条线上的 WSAGetLastError() 但没有其他的,谢谢你指出这一点。我已经更新了当前的错误代码和翻译。
  • 确实是的问题。现在的问题是 WSAECONNREFUSED,这仅仅意味着在您尝试连接的 IP:port 上没有任何监听。
  • 在我做出条件语句之前它不起作用,看看哪里出错了;这是一个问题,但仅在我检查问题所在时才引入。现在的问题是,为什么会出现这个错误?在我的服务器中,该 IP:Port 上有一个侦听器
  • 真的。你能 Telnet 到它吗?来自这个客户端主机?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2014-12-26
  • 1970-01-01
相关资源
最近更新 更多