2010-02-07 8 views
0

Hey im écrire un client écho, et pour une raison quelconque, la fonction connectsock retourne une erreur, et retourne un INVALID_SOCKET. Je ne peux pas comprendre pourquoi est-ce. Quelqu'un peut-il me dire pourquoiImpossible de se connecter à la socket

/********************************* 
* echo1.cpp     * 
*        * 
* Echo client - version 1  * 
**********************************/ 
#include <winsock2.h> 
#pragma comment(lib, "ws2_32.lib") 
#include <string> 
#include <iostream> 
using namespace std; 

const int MAXBUF = 128; 
const int MAXNAME = 80; 

SOCKET connectsock (char*, char*, char*); 

int main (int argc, char **argv) 
{ 
    char msg[MAXBUF] = ""; 
    char buf[MAXBUF] = ""; 
    char host[MAXNAME] = ""; 
    char service[MAXNAME] = ""; 
    int len; 
    SOCKET s; 

    /* Must always initialize the Windows Sockets TCP/IP library */ 
    WORD wVersion = 0x0202; 
    WSADATA wsaData; 
    int iResult = WSAStartup(wVersion, &wsaData); 
    if (iResult != 0) 
    { 
     cout << "Unable to initialize Windows Socket library." << endl; 
     return 0; 
    } 


    string hostaddress = argv[1]; 

    if(argv[2] == NULL) 
    { 
     strcpy_s(service, MAXNAME, "7"); 
    } 
    else 
    { 
     strcpy_s(service, MAXNAME, argv[2]); 
    } 

    strcpy_s(host, MAXNAME, hostaddress.c_str()); 



    s = connectsock(host, service, "tcp"); 
    if (s != INVALID_SOCKET) 
    { 

     cout <<"Message?"; 
     cin.getline(msg, MAXBUF); 


     // Now, let's try to send the message to the remote machine 


     len = send(s, msg, (int) strlen(msg), 0); 
     if (len > 0) 
     { 
      cout << "Number of bytes sent: " << len << endl; 
      cout << endl; 
     } 
     else 
     { 
      cout << "Unable to send message to remote machine." << endl; 
      return 0; 
     } 

     // Message was sent. Is there a reply from the remote machine? 
     len = recv(s, buf, sizeof(buf), 0); 
     if (len > 0) 
     { 
      cout << "Received message: "; 
      for (int i=0; i<len; i++) cout << buf[i]; 
      cout << endl; 
      cout << "Number of bytes received: " << len << endl << endl; 
     } 
     cout << endl << endl; 

     /* Close the socket (and thus the connection) */ 
     shutdown(s,1); 
     closesocket(s); 
    } 
    WSACleanup(); 
} 


/*------------------------------------------------------------------ 
* connectsock - allocate & connect a remote socket using TCP or UDP 
*------------------------------------------------------------------ 
*/ 
SOCKET connectsock (char *host, char *service, char *protocol) 
{ 
    struct hostent *phe; 
    struct servent *pse; 
    short port; 
    int  ihost; 


    port = htons((u_short) atoi(service)); // 1st try to convert string to integer 
    if (port == 0) 
    {      // if that doesn't work, call service function 
     pse = getservbyname(service,NULL); 
     if (pse) 
     { 
      port = pse->s_port; 
     } 
     else 
     { 
      cout << "Invalid service request." << endl; 
      return INVALID_SOCKET; 
     } 
    } 
/* 
    cout << "Service: " << service << endl; 
    cout << "Port: " << htons(port) << endl; 
*/ 


    ihost = inet_addr(host);  
    if (ihost == INADDR_NONE) 
    { 
     phe = gethostbyname(host); 
     if (phe) 
     { 
      memmove(&ihost, phe->h_addr, phe->h_length); 
     } 
     else 
     { 
      cout << "Invalid Host." << endl; 
      return INVALID_SOCKET; 
     } 
    } 
/* 
    cout << "Network address for hostname:   " << host << endl; 
    cout << "32-bit address in Network Byte Order: " << ihost << endl; 
    cout << "32-bit address in Host Byte Order: " << ntohl(ihost) << endl; 

    struct in_addr in; 
    in.S_un.S_addr = ihost; 
    cout << "Address as dotted decimal:   " << inet_ntoa(in) << endl; 

*/ 

    struct sockaddr_in remote; 
    SOCKET s;     

    if (_stricmp(protocol, "tcp") == 0) 
    { 
     s = socket(AF_INET, SOCK_STREAM, 0); 

     if (s < 0 || s == INVALID_SOCKET) 
     { 
      cout << "Cannot create socket" << endl; 
      return INVALID_SOCKET; 
     } 


     memset(&remote, 0, sizeof(remote)); 
     remote.sin_family = AF_INET; 
     remote.sin_port = htons((u_short) atoi(service)); 
     remote.sin_addr.s_addr = inet_addr(host); 


     int status = connect(s, (LPSOCKADDR) &remote, sizeof(SOCKADDR)); 

     if (status == SOCKET_ERROR) 
     { 
      cout << "Remote host/service not found - or connection refused" << endl; 
      return INVALID_SOCKET; 
     } 
    } 

    else if (_stricmp(protocol,"udp") == 0) 
    { 
     s = socket(AF_INET, SOCK_DGRAM, 0); 
     if (s < 0 || s == INVALID_SOCKET) 
     { 
      cout << "Cannot create socket" << endl; 
      return INVALID_SOCKET; 
     } 
    } 
    else 
    {         // Unknown or unsupported protocol request 
     cout << "Invalid Protocol" << endl; 
     return INVALID_SOCKET; 
    } 

    return s; 
} 
+0

Il est clair que la fonction 'connectsock()' peut retourner INVALID_SOCKET pour plusieurs raisons. Qu'est-ce que la fonction imprime lorsque vous l'appelez? –

+0

Qu'est-ce qui échoue exactement? Est-ce le connect, le gethostbyname, autre chose? –

+0

oui - quel cout est en train de tirer. Ensuite, ajoutez GetLastError() pour trouver le code d'erreur win32 – pm100

Répondre

3

Je pense que vous devez utiliser

 remote.sin_port = port; 

au lieu de ce que vous utilisez:

 remote.sin_port = htons((u_short) atoi(service)); 

parce qu'à un moment donné avant dans la fonction que vous essayez déjà de convertir le service en un numéro de port. Si le service est spécifié par un nom, comme il semble dans votre exemple, ce code donnera toujours un remote.sin_port de 0.

+0

Bonne prise. Cela dit, il devrait réellement faire 'remote.sin_port = port;' car le port est déjà dans l'ordre du réseau. –

+0

R Samuel: tu as raison. Je modifie ma réponse. –

0

Lorsque vous exécutez ce code, fournissez-vous éventuellement un socket déjà utilisé? Dans Windows, vous pouvez faire

netstat -a 

Et jeter un oeil pour vous assurer que la prise est pas déjà en cours d'utilisation.

Remarque: Je ne suis pas un utilisateur de fenêtre, donc la commande peut maintenant fonctionner.

+2

sysinternals tcpview est un joli équivalent gui de netstat – pm100

0

Sur la base de l'œil pointu de @ Diego, j'ai également remarqué un second problème. Ce code:

remote.sin_addr.s_addr = inet_addr(host); 

est étrange parce que plus tôt vous avez vérifié inet_addr puis retombé sur gethostbyname si inet_addr a échoué. Donc, si vous avez fourni un nom d'hôte, cela causera également des problèmes. Vous devez changer cela pour:

remote.sin_addr.s_addr = ihost; 
+0

J'ai essayé, ça et ça n'a pas fonctionné – Zerobu

+0

J'ai essayé de le changer avec ihost, mais il produit quand même les mêmes résultats – Zerobu

Questions connexes