2016-07-08 14 views
0

BSD-POSIX TCPソケットクラスを作成しましたが、問題があります.2つの無線ネットワークがあります.1つはADSLルータで、もう1つはAndroidデバイスによってホットスポットされています。私はADSLルータwifiに接続すると、私はすべてのデータを受信することはできません。ソケットはデータを送信することができますが、私はホットスポットWifi(Androidデバイス)に接続するとresponse.Butはありません、プログラムはデータを受信することができます。 「Tはまた、私は成功した送信されdata.DataをキャプチャするWiresharkのを使用しますが、何のreceive.Hereはありませんproblem.Both WIFIネットワークがfine.Andに取り組んでいるか知っている私のコードです:C++、TCPソケットはデータを受け取ることができません

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

EDIT:リセットが解決しよう無線LANルータ。

+0

まず、正式なHTTP 1.1リクエストはありません。それ以外の場合は、 'Host'ヘッダーがありません。第2に、 'recv'を一度だけ呼び出すので、受信するデータ量は任意です。 –

+0

@DavidSchwartz私はwhileループを使用しましたが、response.iは非常に多くの他のホストも試しましたが、coutにスティックがありません<< e.ReceiveData(100);それは非ブロックではないからです。 –

+0

'main'はソケット非ブロックを設定しません。そうした場合、コードはひどく壊れてしまいます。 *しないでください!* –

答えて

0

あなたは、いくつかの重大なバグがあります

  1. はあなたの受信機能は、条件を「ブロックする」ので、それは、非ブロッキングソケットで確実に動作しませんをサポートするためのコードを全く持っていません。

  2. 受信機能では、エラーがあるかどうかを確認する信頼できる方法はありません(空の文字列ではありません)。エラー時にソケット値が破損するため、エラーが発生した後に再度呼び出すと、悲惨なことになります。しかし、これを回避する方法はまったくありません。

  3. ソケットをNULLに設定しました。しかし、何もソケットのための無効な値をNULLにします。 WIN32では、INVALID_SOCKETを使用します。他のプラットフォームでは、-1を使用します。

さらに小さな問題があります。要求はHTTP 1.1準拠を要求しますが、HTTP 1.1準拠の要求ではありません。たとえば、HTTP 1.1では、「ホスト」ヘッダーが必須になります。あなたがサポートするつもりのないプロトコルに準拠していると主張しないでください。チャンクエンコーディングを使用した返信を受け取ったらどうなりますか? おそらく起こっていることは、受信が「ブロックする」状態に遭遇し、ソケットが壊れていて、無効なソケットで再度受信を呼び出すということです。

+0

上記のどれも私の問題です。このhttpリクエストはgoogle.comで正常に動作します。テストすることもできます。また、 "Host:www.google.com"を追加しました。エラーを避けるために、私はs = NULLを使用しました。 while(ESocket.isConnected())を使うことで、接続を確認できます(s!= null)。 –

+0

私は99%があなたの問題だと確信しています。あなたの受信機能を修正して、 "ブロックする"という指示を正しくサポートすれば、問題は消えてしまいます。 –

+1

また、あなたが私たちに与えたコードは、実際にエラーが発生したコードと似ていませんか?そうすれば、非常にイライラすることになります。このようなwhileループは表示されません。あなたは、ソケット非ブロックを設定する関数への呼び出しを何も表示しません。 :/ –

関連する問題