TCP和UDP同时转发,UDP超时问题
我做了一个服务器的socket程序,就是受到客户端的数据,然后完全转发出去,不做任何改变,可是现在的问题是如果对方给我发一个UDP,一个TCP,交替发的话,60000多次接受的话就会有4次左右UDP超时,代码如下:
主函数如下:
DWORD WINAPI ThreadTcpEcho( LPVOID lpParam ) ;
DWORD WINAPI ThreadUdpEcho( LPVOID lpParam ) ;
int _tmain(int argc, char* argv[])
{
//----------------------
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("Error at WSAStartup()\n");
return false;
}
HANDLE hTcp = CreateThread( NULL, 0, ThreadTcpEcho, 0, 0, NULL);
HANDLE hUdp = CreateThread( NULL, 0, ThreadUdpEcho, 0, 0, NULL);
while (1)
{
char key = getch();
if ('q' == key || 'Q' == key)
{
TerminateThread(hTcp, 0);
TerminateThread(hUdp, 0);
break;
}
}
WSACleanup();
return 0;
}
DWORD WINAPI ThreadTcpEcho( LPVOID lpParam )
{
CTcpNet m_tcpServer;
while (1)
{
if (true == m_tcpServer.NetInit()) //初始化TCP
m_tcpServer.NetEcho(); //接受并转发数据
m_tcpServer.NetClose();
}
return 0;
}
DWORD WINAPI ThreadUdpEcho( LPVOID lpParam )
{
CUdpNet m_udpServer;
while (1)
{
if (true == m_udpServer.NetInit())//初始化UDP
m_udpServer.NetEcho(); //接受并转发数据
m_udpServer.NetClose();
}
return 0;
}
UDP的代码如下:
bool CUdpNet::NetInit(void)
{
//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
UDPsocket = socket(AF_INET,SOCK_DGRAM,0);
if (UDPsocket == INVALID_SOCKET) {
printf("[UDP]--Error at socket(): %ld\n", WSAGetLastError());
//WSACleanup();
return false;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = server_IP;
service.sin_port = server_Port;
if (bind( UDPsocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("[UDP]--bind() failed.\n");
closesocket(UDPsocket);
//WSACleanup();
return false;
}
printf("[UDP]--Start UDP communication...\n");
return true;
}
void CUdpNet::NetClose()
{
closesocket(UDPsocket);
}
void CUdpNet::NetEcho()
{
sockaddr_in client;
int clientLen = sizeof(client);
char revbuf[65535];
unsigned short revlength;
revlength = 65535;
while (1)
{
int iResult = recvfrom( UDPsocket, revbuf, revlength, \
0, (sockaddr *)(&client), &clientLen);
//printf("aaa");
if ( iResult > 0 )
{
sendto(UDPsocket, revbuf, iResult, 0, (sockaddr *)(&client), clientLen);
//printf("Bytes received: %d\n", iResult);
}
else if ( iResult == 0 )
{
printf("[UDP]--Connection closed.\n");
return;
}
else if ( iResult == SOCKET_ERROR )
{
printf("[UDP]--Connection error.\n");
return;
}
}
}
TCP的如下:
bool CTcpNet::NetInit(void)
{
//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ListenSocket == INVALID_SOCKET) {
printf("[TCP]--Error at socket(): %ld\n", WSAGetLastError());
//WSACleanup();
return false;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = server_IP;
service.sin_port = server_Port;
if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ListenSocket);
//WSACleanup();
return false;
}
//----------------------
// Listen for incoming connection requests.
// on the created socket
if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
printf("[TCP]--Error listening on socket.\n");
closesocket(ListenSocket);
//WSACleanup();
return false;
}
//----------------------
// Create a SOCKET for accepting incoming requests.
printf("[TCP]--Waiting for client to connect...\n");
//----------------------
// Accept the connection.
int ClientAddrLen = sizeof(ClientAddr);
AcceptSocket = accept( ListenSocket, (sockaddr *)(&ClientAddr), &ClientAddrLen );
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
//WSACleanup();
return false;
} else
printf("[TCP]--Client %d.%d.%d.%d connected.\n", ClientAddr.sin_addr.s_net, \
ClientAddr.sin_addr.s_host, \
ClientAddr.sin_addr.s_lh, \
ClientAddr.sin_addr.s_impno);
// No longer need server socket
closesocket(ListenSocket);
return true;
}
void CTcpNet::NetClose()
{
closesocket(AcceptSocket);
}
void CTcpNet::NetEcho()
{
char revbuf[65535];
unsigned short revlength;
revlength = 65535;
while (1)
{
/*TIMEVAL tWait;
tWait.tv_sec = 0;
tWait.tv_usec = 1000000; // wait for 10000us
fd_set revSet;
FD_ZERO(&revSet);
FD_SET(AcceptSocket, &revSet);
int iResult = select(1, &revSet, NULL, NULL, &tWait);
if ( iResult == 0 )
{
printf("[TCP]--Connection from client %d.%d.%d.%d closed.\n", ClientAddr.sin_addr.s_net, \
ClientAddr.sin_addr.s_host, \
ClientAddr.sin_addr.s_lh, \
ClientAddr.sin_addr.s_impno);
return;
}
else if ( SOCKET_ERROR == iResult )
{
printf("[TCP]--Connection from Client %d.%d.%d.%d error.\n", ClientAddr.sin_addr.s_net, \
ClientAddr.sin_addr.s_host, \
ClientAddr.sin_addr.s_lh, \
ClientAddr.sin_addr.s_impno);
return;
}
*/
iResult = recv(AcceptSocket, revbuf, revlength, 0);
if(iResult == SOCKET_ERROR)
{
printf("failed to connect %d\n",GetLastError());
return ;
}
else if ( iResult > 0 )
{
send(AcceptSocket, revbuf, iResult, 0);
//printf("Bytes received: %d\n", iResult);
}
}
}
现在的问题就是:
1。这段代码的话,我交替转发TCP和UDP各60000次的话,TCP无超时,UDP超时4次左右。
但是如果加上TCP的注释掉的部分,也就是下面的代码:
TIMEVAL tWait;
tWait.tv_sec = 0;
tWait.tv_usec = 1000000; // wait for 10000us
fd_set revSet;
FD_ZERO(&revSet); //清零
FD_SET(AcceptSocket, &revSet);//将接受的socket对应为置1,如果accept接受错了,就会使第1位置1
int iResult = select(1, &revSet, NULL, NULL, &tWait);//检测前2位是否有置1的,如果无,则连接正确
if ( iResult == 0 )
{
printf("[TCP]--Connection from client %d.%d.%d.%d closed.\n", ClientAddr.sin_addr.s_net, \
ClientAddr.sin_addr.s_host, \
ClientAddr.sin_addr.s_lh, \
ClientAddr.sin_addr.s_impno);
return;
}
else if ( SOCKET_ERROR == iResult )
{
printf("[TCP]--Connection from Client %d.%d.%d.%d error.\n", ClientAddr.sin_addr.s_net, \
ClientAddr.sin_addr.s_host, \
ClientAddr.sin_addr.s_lh, \
ClientAddr.sin_addr.s_impno);
return;
}
UDP超时的次数就会很少,偶尔会有一次,我对这段代码理解可能有误,我的理解在上面注释了。而且我感觉这段话没有必要吧,本身TCP的recv函数就阻塞的,加了这段话后倒地什么意思啊?
3。我的端口号两个全是7,可以吗,不会又冲突吗,是不死端口号相同的话,TCP和UDP用的缓冲区就一样了啊?