winsock select() 函数返回 0
winsock select() function returning 0
我正在 MFC 中实现 TFTP 客户端应用程序。下面是两个函数:
1) 连接服务器功能..
int TFTPClient::connectToServer() {
cout << "Connecting to " << server_ip << " on port " << server_port << endl;
socket_descriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket_descriptor == -1) {
throw new ETFTPSocketCreate;
}
client_address.sin_family = AF_INET;
client_address.sin_port = htons(server_port); //- taip pat turi buti ir serveryje!
client_address.sin_addr.s_addr = inet_addr(this->server_ip);
#ifdef WIN32
//memset(client_address.sin_zero, 0, sizeof(client_address.sinzero);
//- suvienodinam SOCKADDR_IN ir SOCKADDR strukturu dydzius
#endif
connection = connect(socket_descriptor, (const struct sockaddr *)&client_address, sizeof(client_address));
if (connection != 0) {
cout << "Unable to connect to an address\n";
return -1;
}
DEBUGMSG("Successfully connected");
AfxMessageBox("Successfully connected");
return 1;
}
2) 等待响应...
int TFTPClient::waitForPacket(TFTP_Packet* packet, int timeout_ms) {
packet->clear();
fd_set fd_reader;
timeval connection_timer;
connection_timer.tv_sec = timeout_ms / 1000; // = 2
connection_timer.tv_usec = 0;
FD_ZERO(&fd_reader);
FD_SET(socket_descriptor, &fd_reader);
int select_ready = select(socket_descriptor + 1, &fd_reader, NULL, NULL, &connection_timer);
if (select_ready == -1) {
#ifdef WIN32
cout << "Error in select(), no: " << WSAGetLastError() << endl;
#else
cout << "Error in select(): " << endl;
#endif
return TFTP_CLIENT_ERROR_SELECT;
} else if (select_ready == 0) {
DEBUGMSG("Timeout");
return TFTP_CLIENT_ERROR_TIMEOUT;
}
int receive_status;
receive_status = recv(socket_descriptor, (char*)packet->getData(), TFTP_PACKET_MAX_SIZE, 0);
if (receive_status == 0) {
cout << "Connection was closed by server\n";
return TFTP_CLIENT_ERROR_CONNECTION_CLOSED;
}
if (receive_status == SOCKET_ERROR) {
DEBUGMSG("recv() error in waitForPackage()");
return TFTP_CLIENT_ERROR_RECEIVE;
}
packet->setSize(receive_status);
return TFTP_CLIENT_ERROR_NO_ERROR;
}
函数2中的select函数returns每次我运行申请0次,表示超时。我的问题:有没有另一种方法可以在不使用 select() 的情况下实现整个功能?或者在我调用 recv 之前是否需要此功能?我不确定为什么会超时,我知道我只需要在发送下一个数据包之前从服务器接收到确认并循环直到文件完全传输。
如果您只有一个文件描述符需要担心,并且想无限期地等待,请不要理会 select
。只需调用 recv
,它将阻塞直到您获得数据。
我正在 MFC 中实现 TFTP 客户端应用程序。下面是两个函数:
1) 连接服务器功能..
int TFTPClient::connectToServer() {
cout << "Connecting to " << server_ip << " on port " << server_port << endl;
socket_descriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket_descriptor == -1) {
throw new ETFTPSocketCreate;
}
client_address.sin_family = AF_INET;
client_address.sin_port = htons(server_port); //- taip pat turi buti ir serveryje!
client_address.sin_addr.s_addr = inet_addr(this->server_ip);
#ifdef WIN32
//memset(client_address.sin_zero, 0, sizeof(client_address.sinzero);
//- suvienodinam SOCKADDR_IN ir SOCKADDR strukturu dydzius
#endif
connection = connect(socket_descriptor, (const struct sockaddr *)&client_address, sizeof(client_address));
if (connection != 0) {
cout << "Unable to connect to an address\n";
return -1;
}
DEBUGMSG("Successfully connected");
AfxMessageBox("Successfully connected");
return 1;
}
2) 等待响应...
int TFTPClient::waitForPacket(TFTP_Packet* packet, int timeout_ms) {
packet->clear();
fd_set fd_reader;
timeval connection_timer;
connection_timer.tv_sec = timeout_ms / 1000; // = 2
connection_timer.tv_usec = 0;
FD_ZERO(&fd_reader);
FD_SET(socket_descriptor, &fd_reader);
int select_ready = select(socket_descriptor + 1, &fd_reader, NULL, NULL, &connection_timer);
if (select_ready == -1) {
#ifdef WIN32
cout << "Error in select(), no: " << WSAGetLastError() << endl;
#else
cout << "Error in select(): " << endl;
#endif
return TFTP_CLIENT_ERROR_SELECT;
} else if (select_ready == 0) {
DEBUGMSG("Timeout");
return TFTP_CLIENT_ERROR_TIMEOUT;
}
int receive_status;
receive_status = recv(socket_descriptor, (char*)packet->getData(), TFTP_PACKET_MAX_SIZE, 0);
if (receive_status == 0) {
cout << "Connection was closed by server\n";
return TFTP_CLIENT_ERROR_CONNECTION_CLOSED;
}
if (receive_status == SOCKET_ERROR) {
DEBUGMSG("recv() error in waitForPackage()");
return TFTP_CLIENT_ERROR_RECEIVE;
}
packet->setSize(receive_status);
return TFTP_CLIENT_ERROR_NO_ERROR;
}
函数2中的select函数returns每次我运行申请0次,表示超时。我的问题:有没有另一种方法可以在不使用 select() 的情况下实现整个功能?或者在我调用 recv 之前是否需要此功能?我不确定为什么会超时,我知道我只需要在发送下一个数据包之前从服务器接收到确认并循环直到文件完全传输。
如果您只有一个文件描述符需要担心,并且想无限期地等待,请不要理会 select
。只需调用 recv
,它将阻塞直到您获得数据。