您的位置:首页 > 理论基础 > 计算机网络

UDP to TCP 数据转发

2008-04-06 09:42 531 查看
提供UDP客户端到TCP服务器的访问的数据转发。有时候我们的服务器提供TCP的数据包格式,可是由于种种原因,我们的客户端只能通过UDP来访问。本文就是提供UDP到TCP的数据转发的功能。本代理接收UDP客户连接请求后,把数据转发到TCP服务器,同时把TCP服务器回送的数据,转发回UDP客户。
设计

//主程序
Main()
{
beginthread(u2tMainThread());
}

//主线程
u2tMainThread(Param)
{
while(true)
{
创建"本地接收 UDP SOCK"
while(read >0)
{
等待 UDP 数据包
收到数据后,查找"目标 TCP SOCK"
if(没有找到)
{
创建一个新的"目标 TCP SOCK"
"目标 TCP SOCK"连接成功后,创建"u2t wait thread"
}
通过"目标 TCP SOCK"发送数据
}
}
}

//t2u Wait Thread 线程
u2t Wait Thread (Param)
{
创建"目标 TCP SOCK"->"连接 UDP SOCK"数据转发Thread
等待线程结束
释放SOCK资源
}

//TCP2UDP 数据转发线程
TCP2UDP Thread(Param)
{
SOCK FROM,TO
while(read >0)
{
read(From,Buff);
Sendto(To,Buff);
}
}

参考代码

参数结构
struct AGENTTCPUDPGATEWAYINFO
{
char TargetIP[40];
int TargetPort;
int LocalPort;
int LocalTmpPort;
};

//主线程
DWORD u2tmainthread(LPVOID lpvoid)
{
AGENTTCPUDPGATEWAYINFO *pasi = (AGENTTCPUDPGATEWAYINFO*)lpvoid;
AGENTTCPUDPGATEWAYINFO asi;
memcpy(&asi,pasi,sizeof(AGENTTCPUDPGATEWAYINFO));
delete pasi; pasi = NULL;
//-t

//如果模式为u2t,那么此地址结构是UDP Client的地址,此地址在接收到UDP Client数据后填充

int iRet;
struct sockaddr_in UDPLocal,Target;
SOCKET sListen,s[2];//s[0]=>UDP socket s[1]=>TCP socket
HANDLE hThread[2]={NULL,NULL};

printf("/nOK!Work mode is udp2tcp.");

//监听本地UDP port的地址结构
UDPLocal.sin_family=AF_INET;
UDPLocal.sin_addr.s_addr=INADDR_ANY;
UDPLocal.sin_port=htons(asi.LocalPort);
//目标地址结构
Target.sin_family=AF_INET;
Target.sin_addr.s_addr=inet_addr(asi.TargetIP);
Target.sin_port=htons(asi.TargetPort);
//开始循环
while(1)
{
printf("/n/n************Udp2Tcp Start new**************/n/n");
_DelSock(s[0]);
//创建一个UDP socket
s[0]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(s[0]==INVALID_SOCKET)
{
ShowError("/nUdp2Tcp:Create UDP socket");
Sleep(5000);
continue;
}
//bind UDP socket
iRet=bind(s[0],(struct sockaddr *)&UDPLocal,sizeof(UDPLocal));
if(iRet == SOCKET_ERROR)
{
printf("/nUdp2Tcp:Bind UDP port %d failed.",asi.LocalPort);
Sleep(5000);
continue;
}
else
printf("/nUdp2Tcp:Bind UDP port %d ok.",asi.LocalPort);

// DWORD threadid=GetCurrentThreadId();
struct sockaddr_in from;
int dwSize=sizeof(from);
char incomingbuff[maxsize];
int read = 1;
while(read >0)
{
read=recvfrom(s[0],incomingbuff,maxsize,0,(SOCKADDR *)&from,&dwSize);
if(read <=0 ) break;
s[1] = udpsvrGetSock1(from) ;
if(s[1] == 0)
{
//然后才TCP connect到Target监听的TCP Port
//创建一个TCP socket
s[1]=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(s[1]==INVALID_SOCKET)
{
ShowError("/nUdp2Tcp:Create TCP socket");
Sleep(5000);
continue;
}
//connect to Target
while(1)
{
iRet=connect(s[1],(SOCKADDR *)&Target,sizeof(Target));
if(iRet!=0)
{
printf("/nUdp2Tcp:Connect to Target TCP %s:%d failed.Wait for try again.",asi.TargetIP,asi.TargetPort);
Sleep(1000);
}
else
{
printf("/nUdp2Tcp:Connent to Target TCP %s:%d ok.",asi.TargetIP,asi.TargetPort);
break;
}
}
DATAREDIRDPARAM* ptdataredird = new DATAREDIRDPARAM;
ptdataredird->sock[0] = s[0];//udp
ptdataredird->sock[1] = s[1];//tcp
memcpy(&ptdataredird->sinudp ,&from,sizeof(sockaddr_in));
ptdataredird->sinudpisfilled = TRUE;
udpsvrAddDataRedird(ptdataredird);
DATAREDIRDPARAM* ptdataredird2 = new DATAREDIRDPARAM;
memcpy(ptdataredird2,ptdataredird,sizeof(DATAREDIRDPARAM));
DWORD threadid;
HANDLE htcp2udpThread = CreateThread(NULL,0,u2twaitthread,(LPVOID)ptdataredird2,NULL,&threadid);
CloseHandle(htcp2udpThread);
}
printf("/ntUdp2Tcp: recvfrom %d bytes.",read);
int npos=0;
while(npos < read)
{
int nsendcount = send(s[1],incomingbuff+npos,read-npos,0);
if(nsendcount <= 0 )
{
udpsvrDelDataRedird(s[1]);
break;
}
printf("/ntUdp2Tcp: send %d bytes.",nsendcount);
npos += nsendcount;
}
}
udpsvrDelAllDataRedird(s[0]);
printf("/n/n**************OK!Udp2Tcp do next******************/n/n");
}//end of while
if(sListen!=INVALID_SOCKET) closesocket(sListen);
return 0;
}
DWORD u2twaitthread(LPVOID lpvoid)
{
DATAREDIRDPARAM* pdrp = (DATAREDIRDPARAM*)lpvoid;
HANDLE hThread;
DWORD id;
hThread = CreateThread(NULL,0,tcp2udp,(LPVOID)pdrp,NULL,&id);
_AddThread(hThread);
DWORD waiter;
waiter = WaitForSingleObject(hThread,INFINITE);
udpsvrDelDataRedird(pdrp->sock[1]);
_DelThread(hThread);
printf("/nUdp2Tcp: Socket closed./n");
delete pdrp;
ExitThread(0);
return 0;
}

//tcp 2 udp 代码
//从sock[1]=>TCP socket读
//往sock[0]=>UDP socket写
DWORD tcp2udp(LPVOID lpvoid)
{
DATAREDIRDPARAM *tudp = (DATAREDIRDPARAM*)lpvoid;
SOCKET *s = tudp->sock;

DWORD threadid=GetCurrentThreadId();
printf("/n***New TCP2UDP %d recv %d sendto %d./n",threadid,s[1],s[0]);

char incomingbuff[maxsize];
int read = 1;

int iUDPRepeat=3;//UDP发送失败后重复的次数
while(read >0)
{
read = recv(s[1],incomingbuff, maxsize,0);
if(read <=0 ) break;
printf("/nTCP2UDP Thread %d recv %d bytes.",threadid,read);
iUDPRepeat = 3;
int npos=0;
while(npos < read)
{
int nsendcount=sendto(s[0],incomingbuff+npos,read-npos,0,(SOCKADDR *)&tudp->sinudp,sizeof(tudp->sinudp));
if(nsendcount == SOCKET_ERROR)
{
ShowError("sendto");
//重复发送次数自减一
if((iUDPRepeat--)>0)
{
printf("/nTry %d times to send.",iUDPRepeat);
continue;
}
}
if(nsendcount <= 0 ) return 0;
printf("/nTCP2UDP[%d] sendto %s:%d %d bytes.",threadid,inet_ntoa(tudp->sinudp.sin_addr),ntohs(tudp->sinudp.sin_port),nsendcount);
npos += nsendcount;
}
}
printf("/nTCP2UDP %d LastError %d",threadid,GetLastError());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: