c - Tilslutning til lokal virtuel maskine

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har mistanke om, at dette har en nem løsning, jeg overvejer, sandsynligvis at gøre med klienten eller hvordan denne er oprettet.

Anyway, jeg forsøger at oprette en simpel ekkoserver/klient for at forstå det grundlæggende i socket programmering. Jeg har en virtuel maskine, der kører Linux Mint, og værten kører Windows 10. Den virtuelle maskine jeg indstiller til at køre serveren c-kode, og Windows kører klienten.


Jeg begyndte at gøre serveren kode


//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;
}


efter det testede jeg det ved at åbne en anden terminal i gæstemaskinen og skrev 'telnet localhost 8888' og indtaste de ønskede strings.


Denne test fungerede så nu på min Windows-maskine for at skabe klientsiden af ​​socket programmeringen:


#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
");

    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
", WSAGetLastError());
        return 1;
    }
    printf("Connection Accepted
");

    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
    }
}


Nu, når serveren stadig kører, når jeg prøver klientsiden, får jeg svaret 'Connection Error' (fra linje 35). Efter at have set på både Unix og WinSock eksempler, er jeg ikke sikker på, hvorfor jeg ville fejle forbindelsen. Jeg formoder, at det måske har noget at gøre med en Windows til Linux VM, men jeg er ikke sikker.


--- UPDATE ---
Efter at have opdateret det uheldige semikolon og tilføjet WSAGetLastError, viser det en fejlkode på 10061; dette oversætter til
'Connection afvist.
Der kunne ikke oprettes forbindelse, fordi målcomputeren aktivt nægtede det. Dette skyldes sædvanligvis, at man opretter forbindelse til en tjeneste, der er inaktiv på den udenlandske vært - det vil sige en uden serverprogram, der kører. '

Bedste reference


[[efter 3. redigering:]]


Sry, bare læs dit spørgsmål igen. Det vigtige er her:



  Den virtuelle maskine jeg indstiller til at køre server c-koden, og Windows kører klienten.



127.0.0.1 er en adresse altid kun lokal til en IP-aktiveret boks. Så du serverer din server på grænsefladen 127.0.0.1 lokal til Linux VM, og klienten forsøger at oprette forbindelse til 127.0.0.0 lokalt til Windows-boksen. Disse to grænseflader er ikke det samme. Resultatet er det indlysende, nemlig klienten finder ikke noget at oprette forbindelse til.


127.0.0.1 (den såkaldte IPv4 local loopback interface e ') kan kun bruges til forbindelser lokal til nøjagtigt en boks.

Andre referencer 1


if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0); {
    printf("Connection Error");
    return 1;
}


Dette er bare en triviel syntaksfejl. Du går ind i blokken ubetinget. Fjern det første semikolon.


Men der er et meget vigtigere punkt at blive gjort. Når du får en fejl fra et systemopkald som connect(), skal du udskrive fejlen . Ikke bare en besked om din egen udformning. Ellers ved du ikke, om du bare har en fejl eller et midlertidigt problem eller et langvarigt problem eller et permanent problem.


Skift printf() til:


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


og derefter don 't fortsæt som om fejlen ikke skete.


Bemærk, at dette gælder for alle systemopkald, herunder især socket(), bind(), listen(), connect(), accept(), recv(), send() og venner.