Winsock服务器无法连接

时间:2011-09-01 18:02:42

标签: c++ windows winapi winsock

我写过(而不是从教程中复制:P)一个winsock服务器,用c ++等待客户端发送消息然后关闭。当客户端和服务器都在我的PC上时服务器工作,但是当我将客户端移动到另一台计算机时,它会失败。 我认为这是我的ip地址的一个问题,但我在命令提示符下输入ipconfig \all时得到的是192.168.254.4。

服务器

//******************************************************************************
//
// Main.cpp
//
// Main source file of the Listener program, which employs blocking sockets and
// Winsock to listen for outside connections.
//
// If you are not using the included Dev-C++ project file, be sure to link with
// the Winsock library, usually wsock32.lib or something similarly named.
//
// Author:  Johnnie Rose, Jr. (johnnie2@hal-pc.org)
// Date:  1/08/03 (version 2)
// Website:  http://www.hal-pc.org/~johnnie2/winsock.html
//
//******************************************************************************

#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#define NETWORK_ERROR -1
#define NETWORK_OK     0

void ReportError(int, const char *);
using namespace std;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
   WORD sockVersion;
   WSADATA wsaData;
   int nret;

   sockVersion = MAKEWORD(2, 2);              // We'd like Winsock version 1.1

   // We begin by initializing Winsock
   WSAStartup(sockVersion, &wsaData);

   // Next, create the listening socket
   SOCKET listeningSocket;

   listeningSocket = socket(AF_INET,          // Go over TCP/IP
                            SOCK_STREAM,      // This is a stream-oriented socket
                            IPPROTO_TCP);     // Use TCP rather than UDP

   if (listeningSocket == INVALID_SOCKET) {
      nret = WSAGetLastError();               // Get a more detailed error
      ReportError(nret, "socket()");          // Report the error with our custom function

      WSACleanup();                           // Shutdown Winsock
      return NETWORK_ERROR;                   // Return an error value
   }

   // Use a SOCKADDR_IN struct to fill in address information
   SOCKADDR_IN serverInfo;

   serverInfo.sin_family = AF_INET;
   serverInfo.sin_addr.s_addr = INADDR_ANY;   // Since this socket is listening for
                                              // connections, any local address will do
   serverInfo.sin_port = htons(8888);         // Convert integer 8888 to network-byte order
                                              // and insert into the port field

   // Bind the socket to our local server address
   nret = bind(listeningSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));

   if (nret == SOCKET_ERROR) {
      nret = WSAGetLastError();
      ReportError(nret, "bind()");

      WSACleanup();
      return NETWORK_ERROR;
   }

   // Make the socket listen
   nret = listen(listeningSocket, 10);        // Up to 10 connections may wait at any
                                              // one time to be accept()'ed

   if (nret == SOCKET_ERROR) {
      nret = WSAGetLastError();
      ReportError(nret, "listen()");

      WSACleanup();
      return NETWORK_ERROR;
   }

   // Wait for a client
   cout << "Waiting for client" << endl;
   SOCKET theClient;

   theClient = accept(listeningSocket,
                      NULL,                   // Address of a sockaddr structure (see explanation below)
                      NULL);                  // Address of a variable containing size of sockaddr struct

   if (theClient == INVALID_SOCKET) {
      nret = WSAGetLastError();
      ReportError(nret, "accept()");

      WSACleanup();
      return NETWORK_ERROR;
   }
   char Buffer[256];
       recv(theClient, Buffer, 256, 0);
       printf(Buffer, 2);
   // Send and receive from the client, and finally,
   closesocket(theClient);
   closesocket(listeningSocket);


   // Shutdown Winsock
   WSACleanup();
   system("PAUSE");
   return NETWORK_OK;
}


void ReportError(int errorCode, const char *whichFunc) {
   char errorMsg[92];                         // Declare a buffer to hold
                                              // the generated error message

   ZeroMemory(errorMsg, 92);                  // Automatically NULL-terminate the string

   // The following line copies the phrase, whichFunc string, and integer errorCode into the buffer
   sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);

   MessageBox(NULL, errorMsg, "socketIndication", MB_OK);
}

客户端

//******************************************************************************
//
// Main.cpp
//
// Main source file of the Connector program, which employs blocking sockets and
// Winsock to connect to an outside server.
//
// If you are not using the included Dev-C++ project file, be sure to link with
// the Winsock library, usually wsock32.lib or something similarly named.
//
// Author:  Johnnie Rose, Jr. (johnnie2@hal-pc.org)
// Date:  1/08/03 (version 2)
// Website:  http://www.hal-pc.org/~johnnie2/winsock.html
//
//******************************************************************************

#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#define NETWORK_ERROR -1
#define NETWORK_OK     0

void ReportError(int, const char *);
using namespace std;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
   WORD sockVersion;
   WSADATA wsaData;
   int nret;
   cout <<"Loading WinSock" << endl;
   sockVersion = MAKEWORD(2, 2);

   // Initialize Winsock as before
   WSAStartup(sockVersion, &wsaData);

   // Store information about the server
   LPHOSTENT hostEntry;
   in_addr iaHost;
   iaHost.s_addr = inet_addr("192.168.254.4");
   hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);     // Specifying the server by its name;
                                                   // another option is gethostbyaddr()
   if (!hostEntry) {
      nret = WSAGetLastError();
      ReportError(nret, "gethostbyaddr()");         // Report the error as before

      WSACleanup();
      return NETWORK_ERROR;
   }

   // Create the socket
   cout <<"Creating Socket";
   SOCKET theSocket;

   theSocket = socket(AF_INET,                      // Go over TCP/IP
                      SOCK_STREAM,                  // This is a stream-oriented socket
                      IPPROTO_TCP);                 // Use TCP rather than UDP

   if (theSocket == INVALID_SOCKET) {
      nret = WSAGetLastError();
      ReportError(nret, "socket()");

      WSACleanup();
      return NETWORK_ERROR;
   }

   // Fill a SOCKADDR_IN struct with address information
   SOCKADDR_IN serverInfo;

   serverInfo.sin_family = AF_INET;
   serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);   // See the explanation in the tutorial
   serverInfo.sin_port = htons(8888);                 // Change to network-byte order and
                                                    // insert into port field
    cout << "Connecting to server" << endl;
   // Connect to the server
   nret = connect(theSocket,
                  (LPSOCKADDR)&serverInfo,
                  sizeof(struct sockaddr));

   if (nret == SOCKET_ERROR) {
      nret = WSAGetLastError();
      ReportError(nret, "connect()");

      WSACleanup();
      return NETWORK_ERROR;
   }

   // Successfully connected!
   char* Buffer;
   send(theSocket, "A", 1, 0);
   recv(theSocket, Buffer, 256,0);
   printf(Buffer,256);
   // Send/receive, then cleanup:
   closesocket(theSocket);
   WSACleanup();

   system("PAUSE");
   return 0;
}


void ReportError(int errorCode, const char *whichFunc) {
   char errorMsg[92];                               // Declare a buffer to hold
                                                    // the generated error message

   ZeroMemory(errorMsg, 92);                        // Automatically NULL-terminate the string

   // The following line copies the phrase, whichFunc string, and integer errorCode into the buffer
   sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);

   MessageBox(NULL, errorMsg, "socketIndication", MB_OK);
}

1 个答案:

答案 0 :(得分:3)

如果您在另一台计算机上运行未修改的客户端代码,它可能仍在尝试连接到“localhost”上的服务器,这不是您想要的。 [编辑:OP已更新其客户端代码,现在正在使用IP地址。]

在典型的家庭/办公室局域网设置中,您可能希望使用IP地址而不是 主机名,用于指定要使用的服务器。您可能还需要检查网络 您指定的端口未被客户端或服务器上的软件防火墙阻止 机器,或服务器和客户端之间的硬件防火墙或路由器。

调试此类问题的一种方法是使用Wireshark之类的工具进行监控 客户端和服务器之间的网络流量。数据包在尝试建立连接时是否离开客户端的计算机?服务器的机器是否看到了请求?一侧或另一侧是否过早关闭连接?请记住,防火墙可以阻止传出流量以及传入流量......