尝试连接winsock时出现错误10061

时间:2014-04-14 21:44:26

标签: c++ winsock

我在同一台计算机上运行客户端和服务器。 客户端通过端口80连接到127.0.0.1。服务器同时侦听端口80。

当我启动客户端并尝试连接时抛出错误10061(目标计算机主动拒绝)。我试图关闭我的本地防火墙,但这并没有改变任何东西。 我肯定会坚持这个。这是连接到服务器的代码:

void Base::Connect(string ip, string port)
{
    int status;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo hints;
    struct addrinfo *servinfo;  // will point to the results

    memset(&hints, 0, sizeof hints); // make sure the struct is empty
    hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

    // get ready to connect
    status = getaddrinfo(ip.c_str(), port.c_str(), &hints, &servinfo);

    // Socket Setup
    if ((ConnectSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == INVALID_SOCKET)
    {
        printf("[NETWORKING] An error occured when setting up socket\n");
    }

    // Connect
    WSACleanup();
    if (connect(ConnectSocket, servinfo->ai_addr, (int)servinfo->ai_addrlen) == SOCKET_ERROR)
    {
        int error = WSAGetLastError();
        printf("Connect error: ", error);
    }
}

这是服务器中侦听传入连接的代码:

int _tmain(int argc, _TCHAR* argv[])
{
// WINDOWS SETUP
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) 
{
    fprintf(stderr, "WSAStartup failed.\n");
    exit(1);
}

// PREPARE TO LAUNCH
int status;
struct sockaddr_storage their_addr;
socklen_t addr_size;
int sockfd, new_fd = 0;

struct addrinfo hints;
struct addrinfo *servinfo;  // will point to the results

memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

if ((status = getaddrinfo(NULL, "80", &hints, &servinfo)) != 0) 
{
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    getchar();
    exit(1);
}

// GET THE FILE DESCRIPTOR  
SOCKET mSocket = INVALID_SOCKET;
mSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);

// WHAT PORT AM I ON
bind(mSocket, servinfo->ai_addr, servinfo->ai_addrlen);

int backlog = 2;
listen(mSocket, backlog);

// SERVER STARTED LISTENING SUCCESFULLY
printf("Server is listenening...\n");

// ACCEPT
printf("Server starts accepting clients...\n");
addr_size = sizeof their_addr;
new_fd = accept(mSocket, (struct sockaddr*)&their_addr, &addr_size);

printf("Server ended");
getchar();

// lose the pesky "Address already in use" error message
char yes='1';

if (setsockopt(mSocket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
} 

return 0;
}

欢迎任何帮助!提前致谢

1 个答案:

答案 0 :(得分:4)

在客户端:

  1. 在致电WSACleanup()之前不要致电connect()
  2. 您没有对getaddrinfo()进行任何错误处理。
  3. 您没有将ai_flags设置为与输入值匹配(例如AI_NUMERICHOST)。
  4. 你没有释放getaddrinfo()返回的记忆。
  5. 您没有考虑将AF_UNSPEC指定为getaddrinfo(),因此可能会返回多个地址。你应该尝试连接所有这些,直到成功为止。
  6. 请改为尝试:

    void Base::Connect(string ip, string port)
    {
        int status, error;
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo hints = {0};
        struct addrinfo *servinfo;  // will point to the results
    
        hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
        hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
        hints.ai_flags = AI_NUMERICHOST; // parse an IP address
        //hints.ai_flags |= AI_NUMERICSERV; // parse a port number (not supported on Windows)
    
        // get ready to connect
        status = getaddrinfo(ip.c_str(), port.c_str(), &hints, &servinfo);
        if (status != 0)
        {
            printf("getaddrinfo error: (%d) %s\n", status, gai_strerror(status));
            return;
        }
    
        addrinfo *addr = servinfo;
        do
        {
            // Socket Setup
            ConnectSocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
            if (ConnectSocket == INVALID_SOCKET)
            {
                printf("socket error: %d\n", WSAGetLastError());
            }
            else
            {
                // Connect
                if (connect(ConnectSocket, addr->ai_addr, addr->ai_addrlen) != SOCKET_ERROR)
                {
                    printf("connected to server\n");
                    break;
                }
    
                printf("connect error: %d\n", WSAGetLastError());
    
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
            }
    
            addr = addr->ai_next;
        }
        while (addr != NULL);
    
        freeaddrinfo(servinfo);
    
        if (ConnectSocket == INVALID_SOCKET)
            printf("unable to connect to server\n");
    }
    

    在服务器端:

    1. 您没有对socket()bind()listen()进行任何错误处理。
    2. 在调用SO_REUSEADDR之前必须启用
    3. bind(),而不是之后。你甚至没有正确启用它。
    4. 你没有释放getaddrinfo()返回的记忆。
    5. 请改为尝试:

      int _tmain(int argc, _TCHAR* argv[])
      {
          // WINDOWS SETUP
          WSAData wsaData;
          if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) 
          {
              fprintf(stderr, "WSAStartup failed.\n");
              exit(1);
          }
      
          // PREPARE TO LAUNCH
          int status;
          struct sockaddr_storage their_addr;
          socklen_t addr_size;
          SOCKET client;
      
          struct addrinfo hints = {0};
          struct addrinfo *servinfo;  // will point to the results
      
          hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
          hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
          hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
          //hints.ai_flags |= AI_NUMERICSERV; // parse a port number (not supported on Windows)
      
          status = getaddrinfo(NULL, "80", &hints, &servinfo);
          if (status != 0) 
          {
              fprintf(stderr, "getaddrinfo error: (%d) %s\n", status, gai_strerror(status));
              getchar();
              exit(1);
          }
      
          // optional, loop through servinfo creating a separate
          // listening socket for each address reported...
      
          // GET THE FILE DESCRIPTOR  
          SOCKET mSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
          if (mSocket == INVALID_SOCKET)
          {
              fprintf(stderr, "socket error: %d\n", WSAGetLastError());
              freeaddrinfo(servinfo);
              closesocket(mSocket);
              getchar();
              exit(1);
          }
      
          // lose the pesky "Address already in use" error message
          BOOL yes = TRUE;
          if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)) == SOCKET_ERROR)
          {
              fprintf(stderr, "setsockopt error: %d\n", WSAGetLastError());
              freeaddrinfo(servinfo);
              closesocket(mSocket);
              getchar();
              exit(1);
          }
      
          // WHAT PORT AM I ON
          if (bind(mSocket, servinfo->ai_addr, servinfo->ai_addrlen) == SOCKET_ERROR)
          {
              fprintf(stderr, "bind error: %d\n", WSAGetLastError());
              freeaddrinfo(servinfo);
              closesocket(mSocket);
              getchar();
              exit(1);
          }
      
          freeaddrinfo(servinfo);
      
          int backlog = 2;
          if (listen(mSocket, backlog) == SOCKET_ERROR)
          {
              fprintf(stderr, "listen error: %d\n", WSAGetLastError());
              closesocket(mSocket);
              getchar();
              exit(1);
          }
      
          // SERVER STARTED LISTENING SUCCESFULLY
          printf("Server is listening...\n");
      
          // ACCEPT
          addr_size = sizeof their_addr;
          client = accept(mSocket, (struct sockaddr*)&their_addr, &addr_size);
          if (client == INVALID_SOCKET)
          {
              fprintf(stderr, "accept error: %d\n", WSAGetLastError());
          }
          else
          {
              char ip[NI_MAXHOST] = {0};
              char port[NI_MAXSERV] = {0};
      
              status = getnameinfo((struct sockaddr*)&their_addr, addr_size, ip, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
              if (status == 0)
                  printf("Client connected from %s:%s\n", ip, port);
              else
                  printf("Client connected. getnameinfo error: (%d) %s\n", status, gai_strerror(status));
      
              //...
      
              closesocket(client);
          }        
      
          closesocket(mSocket);
          printf("Server ended");
      
          getchar();
      
          return 0;
      }