簡體   English   中英

C ++,TCP套接字無法接收數據

[英]C++ , TCP Socket cannot receive data

我創建了一個BSD-POSIX TCP Socket類,現在有一個問題,我有兩個wifi網絡,其中一個是ADSL Router,另一個是Android設備熱點。當我連接到ADSL Router wifi時,我可以根本不接收任何數據。套接字可以發送數據,但是沒有響應。但是當我連接到熱點wifi(Android設備)時,程序可以接收數據。我不知道出了什么問題。網絡工作正常。我也使用Wireshark捕獲數據。數據發送成功,但是沒有接收。這是我的代碼:

-------------------ESocket.cpp---------------------


#include "ESocket.h"
#include "stdio.h"

SOCKET s = NULL;


ESocket::ESocket(string ip,int port)
{
    struct sockaddr_in server;
    if((s = socket(AF_INET , SOCK_STREAM , 0 )) == -1)
    {
        s = NULL;
    }
    server.sin_addr.s_addr = inet_addr(ip.c_str());
    server.sin_family = AF_INET;
    server.sin_port = htons( port );
    if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        s = NULL;
    }
}

ESocket::ESocket(SOCKET e)
{
    s = e;
}

ESocket::~ESocket()
{
    Destruct();
}



bool ESocket::isConnected()
{
    return (s != NULL);
}



int ESocket::Destruct()
{
  #ifdef _WIN32
    return WSACleanup();
  #else
    return 0;
  #endif
}



int ESocket::Close()
{


  int status = 0;
  #ifdef _WIN32
    status = shutdown(s, SD_BOTH);
    if (status == 0) { status = closesocket(s); }
  #else
    status = shutdown(s, SHUT_RDWR);
    if (status == 0) { status = close(s); }
  #endif

  return status;

}


bool ESocket::SendData(string data)
{

    if( send(s , data.c_str() , data.length() , 0) < 0)
    {
        s = NULL;
        return false;
    }
    return true;
}


string ESocket::ReceiveData(int len)
{
    int recv_size;
    char reply[len];
    if((recv_size = recv(s , reply , len , 0)) < 0)
    {
        return "";
    }

    if (recv_size == 0)
    {
        s = NULL;
        return "";
    }
    printf("%i",recv_size);
    reply[recv_size] = '\0';
    return reply;
}





int ESocket::setAsNonBlock()
{

    int res;
    #ifdef _WIN32
    u_long iMode = 1;
    res = ioctlsocket(s, FIONBIO, &iMode);
    #else
    int opts;
    opts = fcntl(s, F_GETFL);
    if(opts < 0)
    {
        res = -1;
    }
    opts = (opts | O_NONBLOCK);
    if(fcntl(s, F_SETFL, opts) < 0)
    {
        res = -1;
    }
    #endif
    return res;
}









-------------------ESocket.h---------------------


#ifndef ESOCKET_H
#define ESOCKET_H

#include <string>
#include <stdio.h>
#include <cstring>

using namespace std;

#ifdef _WIN32
  #ifndef _WIN32_WINNT
    #define _WIN32_WINNT 0x0501
  #endif
  #include <winsock2.h>
#else
typedef int SOCKET;
  #include <sys/socket.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <unistd.h>
  #include <fcntl.h>
#endif

class ESocket
{
    public:
        ESocket(string ip,int port);
        ESocket(SOCKET e);
        virtual ~ESocket();
        int Destruct();
        int Close();
        int setAsNonBlock();
        bool SendData(string data);
        bool isConnected();

        string ReceiveData(int len);

static int Init()
{
  #ifdef _WIN32
    WSADATA wsa_data;
    return WSAStartup(MAKEWORD(1,1), &wsa_data);
  #else
    return 0;
  #endif
}

    static string getIP(char* host)
    {

    struct hostent *he;
    struct in_addr **addr_list;

    char ip[100];


    int i;

    if ( (he = gethostbyname( host ) ) == NULL)
    {
        return "";
    }

    addr_list = (struct in_addr **) he->h_addr_list;

    for(i = 0; addr_list[i] != NULL; i++)
    {

        strcpy(ip , inet_ntoa(*addr_list[i]) );
    }
    string x = ip;
    return x;
    }


    protected:

    private:

};

#endif // ESOCKET_H








------------------------MAIN-----------------------
ESocket::Init();
ESocket e(ESocket::getIP("www.google.com").c_str(),80);
if (e.isConnected())
{
     cout<<e.SendData("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: keep-alive\r\n\r\n");
}
else
{
    printf("Not connected");
    return 0;
}

while (e.isConnected()){
cout<<e.ReceiveData(100);
}
printf("\nEND OF CONNECTION");

編輯:通過重置WiFi路由器解決。

您有幾個嚴重的錯誤:

  1. 您的接收函數沒有支持“禁止阻塞”條件的代碼,因此它將無法與非阻塞套接字可靠地一起工作。

  2. 您的接收函數沒有提供可靠的方法來判斷它是否出錯(與空字符串相反)。 它會在發生錯誤時破壞套接字的值,因此在發生錯誤后再次調用它可能會造成災難性的后果。 但是,它根本無法避免這種情況。

  3. 您將套接字設置為NULL 但是沒有什么可以使NULL成為套接字的無效值。 在WIN32上,使用INVALID_SOCKET 在其他平台上,使用-1。

您還有一個較小的問題。 您的請求聲明符合HTTP 1.1,但不是HTTP 1.1符合請求。 例如,HTTP 1.1強制使用“主機”標頭。 不要聲稱遵守您無意支持的協議。 如果您收到使用分塊編碼的答復,會發生什么情況? 可能發生的情況是,接收遇到“ Would Block”條件,破壞了套接字,然后您使用無效的套接字再次調用了接收,這當然會失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM