我正在研究一个简单的网络服务器示例。它应接受TCP和UDP请求并使用asctime字符串进行应答。 UDP正在解决任何问题。 TCP在Windows上出现了一些问题。我自己在linux上工作,但必须在Windows上运行这个小例子。大学的PC正在运行Windows。因此,为了您的信息,我尝试了交叉编译甚至编译系统本身。
Linux上的实际问题是一切正常。以下代码是我尝试实现非阻塞TCP侦听器,它在获取请求时用asctime-string响应(用户定义的端口不仅仅是13):
void Server::tcpListen(int port)
{
socklen_t size = sizeof(sockaddr);
sockaddr_in remoteHost;
mAddress.sin_port = htons(port);
int r = bind(mTcpSocket, (sockaddr*) &mAddress, sizeof(sockaddr));
if(r < 0)
{
cerr << "Couldn't bind port. (" << std::strerror(errno) << " " << errno << ")" << endl;
#ifdef WIN32
cerr << "WSA Error: " << WSAGetLastError() << endl;
#endif
mTcpServerRunning = false;
return;
}
cout << "TCP:\tListen on port " << port << '\n';
r = listen(mTcpSocket, 5);
if(r < 0)
{
cerr << "Couldn't listen. " << std::strerror(errno) << " " << endl;
mTcpServerRunning = false;
return;
}
time_t t;
struct tm *timeinfo;
std::string timeMsg;
mTcpServerRunning = true;
while(mTcpServerRunning)
{
int cSock = accept(mTcpSocket, (sockaddr*) &remoteHost, &size);
if(cSock < 0)
{
continue;
}
char buf[5];
r = recv(cSock, buf, sizeof(buf), 0);
if(r > 0)
{
time(&t);
timeinfo = localtime(&t);
timeMsg = asctime(timeinfo);
r = send(cSock, (char*) timeMsg.c_str(), timeMsg.length(), 0);
if(r < 0)
{
cerr << "send error: " << errno << endl;
exit(EXIT_FAILURE);
}
uint8_t ip[4];
memcpy(ip, &remoteHost.sin_addr.s_addr, sizeof(ip));
cout << "-----------------------------------------------------" << endl;
cout << "Request-Type: TCP" << " / " << timeMsg.c_str() << endl;
cout << "IP: "
<< (int) ip[0]
<< "." << (int) ip[1]
<< "." << (int) ip[2]
<< "." << (int) ip[3]
<< " / Port (Client): " << remoteHost.sin_port << endl;
cout << "-----------------------------------------------------" << endl;
}
}
close(mTcpSocket);
#ifdef WIN32
WSACleanup();
#endif
mTcpServerRunning = false;
}
为了调试连接,我使用了wireshark,告诉我连接尝试没有得到答复。通过三次握手的初始化工作(SYN-> SYN,ACK-> ACK)。甚至请求(空字符串)也正常工作。 (PSH,ACK - > ACK)但服务器不响应时间字符串。我打开了端口,甚至完全禁用了防火墙。
WSASocket使用有什么问题吗?阻止TCP接收也不起作用。在回答之前我已经考虑了循环重复,然后覆盖了从accept返回的cSock
描述符。
编辑:套接字初始化:
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup (MAKEWORD(1, 1), &wsaData) != 0) {
fprintf (stderr, "WSAStartup(): Couldn't initialize Winsock.\n");
exit (EXIT_FAILURE);
}
#endif
mTcpSocket = socket(AF_INET, SOCK_STREAM, 0);
mUdpSocket = socket(AF_INET, SOCK_DGRAM, 0);
#ifdef _WIN32
unsigned long nonblocking = 1;
// if(ioctlsocket(mTcpSocket,FIONBIO, &nonblocking))
// std::cout << "Couldn't set TCP-Socket to nonblocking mode! ("
// << std::strerror(errno) << ")" << endl;
if(ioctlsocket(mUdpSocket, FIONBIO, &nonblocking))
std::cerr << "Couldn't set UDP-Socket to nonblocking mode! ("
<< std::strerror(errno) << ")" << endl;
#else
int tcpFlags = fcntl(mTcpSocket, F_GETFL, 0);
int udpFlags = fcntl(mUdpSocket, F_GETFL, 0);
if(fcntl(mTcpSocket, F_SETFL, tcpFlags | O_NONBLOCK))
std::cout << "Couldn't set TCP-Socket to nonblocking mode! ("
<< std::strerror(errno) << ")" << endl;
if(fcntl(mUdpSocket, F_SETFL, udpFlags | O_NONBLOCK))
std::cerr << "Couldn't set UDP-Socket to nonblocking mode! ("
<< std::strerror(errno) << ")" << endl;
#endif