我创建了一个BSD-POSIX TCP Socket类,现在遇到了一个问题,我有两个wifi网络,其中一个是ADSL路由器,另一个是由Android设备热点。当我连接到ADSL路由器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路由器解决。
您有几个严重的错误:
您的接收函数没有支持“将阻止”条件的代码,因此它将无法与非阻止套接字可靠地一起工作。
您的receive函数没有提供可靠的方法来判断它是否出错(与空字符串相反)。它会在发生错误时破坏套接字值,因此在发生错误后再次调用它可能会造成灾难性的后果。但是,它根本无法避免这种情况。
您将套接字设置为NULL
。但是没有什么能使NULL
套接字的值无效。在WIN32上,使用INVALID_SOCKET
。在其他平台上,使用-1。
您还有一个较小的问题。您的请求声称符合HTTP 1.1,但它不是HTTP 1.1符合请求。例如,HTTP 1.1强制使用“主机”标头。不要声称您无意支持某个协议。如果您返回使用分块编码的答复,会发生什么情况?可能发生的情况是,receive遇到“ would block”条件,破坏了套接字,然后您使用无效的套接字再次调用receive,这当然会失败。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句