Purpose
Provides data forwarding for access from a tcp client to a UDP server. Sometimes our server provides UDP packet format, but for various reasons,
Our client can only be accessed through TCP. This article provides data forwarding from TCP to UDP. After receiving tcp client connection requests
Data is forwarded to the UDP server, and the data returned by the UDP server is forwarded back to the tcp client.
Design
// Main program
Main ()
{
Beginthread (t2umainthread ());
}
// Main thread
T2umainthread (PARAM)
{
Create "local listening TCP sock"
While (true)
{
Waiting for tcp client connection
After that, create "target UDP sock"
Create and run "t2u wait thread"
}
}
// T2u wait thread
T2u wait thread (PARAM)
{
Create "Connect TCP sock"-> "target UDP sock" data forwarding thread
Create "target UDP sock"-> "Connect TCP sock" data forwarding thread
Wait until the two threads end
Release sock Resources
}
// Tcp2udp data forwarding thread
Tcp2udp thread (PARAM)
{
Sock from,
While (read> 0)
{
Read (from, buff );
Sendto (to, buff );
}
}
// Udp2tcp data forwarding thread
Udp2tcp thread (PARAM)
{
Sock from,
While (read> 0)
{
Readfrom (from, buff );
Send (to, buff );
}
}
Reference Code
Parameter Structure
Struct dataredirdparam
{
Socket sock [2];
/* If the mode is t, the address structure is the UDP client address. After receiving UDP client data, enter
Charge
If the mode is u, the address structure is the target address */
Struct sockaddr_in sinudp;
Bool sinudpisfilled; // indicates whether the data above is filled or not.
Struct icmpheader icmphdr;
Dataredirdparam ()
{
Sinudpisfilled = false;
}
};
// Main thread
DWORD winapi t2umainthread (lpvoid)
{
Agenttcpudpgatewayinfo * Pasi = (agenttcpudpgatewayinfo *) lpvoid;
Agenttcpudpgatewayinfo ASI;
Memcpy (& ASI, Pasi, sizeof (agenttcpudpgatewayinfo ));
Delete Pasi; Pasi = NULL;
//-U
// If the mode is u, the address structure is the target address.
Struct sockaddr_in sinudp;
Bool sinudpisfilled = false; // indicates whether the data above is filled or not.
Int iret;
Struct sockaddr_in udplocal, tcplocal, target;
Socket slisten, s [2]; // s [0] => UDP socket s [1] => TCP socket
Handle hthread [2] = {null, null };
Printf ("/nok! Work mode is tcp2udp .");
// Target address Structure
Target. sin_family = af_inet;
Target. sin_addr.s_addr = inet_addr (ASI. targetip );
Target. sin_port = htons (ASI. targetport );
// If the job is in U mode, listen for a TCP port waiting for the client to connect
// Create a TCP socket
Slisten = socket (af_inet, sock_stream, ipproto_ip );
If (slisten = invalid_socket)
{
Showerror ("/ncreate TCP socket ");
Return-1;
}
// Listen to the address structure of the local TCP port
Tcplocal. sin_family = af_inet;
Tcplocal. sin_port = htons (ASI. localport );
Tcplocal. sin_addr.s_addr = htonl (inaddr_any );
// Bind socket
Iret = BIND (slisten, (sockaddr *) & tcplocal, sizeof (tcplocal ));
If (iret! = 0)
{
Showerror ("bind TCP port ");
_ Delsock (slisten );
Return-2;
}
// Listen socket
If (Listen (slisten, 1) = socket_error)
{
Showerror ("listen ");
_ Delsock (slisten );
Return-3;
}
Sinudp. sin_family = target. sin_family;
Sinudp. sin_addr = target. sin_addr;
Sinudp. sin_port = target. sin_port;
Sinudpisfilled = true;
Printf ("/nlisten TCP 127.0.0.1: % d OK! ", Asi. localport );
// Start the loop
While (1)
{
Printf ("/n ************* OK! Tcp2udp: Start new ***************/n ");
Struct sockaddr_in ADDR;
Int isize = sizeof (ADDR );
// Block the connection to the customer
Printf ("/ntcp2udp: Wait connect to me ......:)");
S [1] = accept (slisten, (struct sockaddr *) & ADDR, & isize );
If (s [1] = invalid_socket)
{
Showerror ("ntcp2udp: accept ");
Sleep (5000 );
Continue;
}
Printf ("/ntcp2udp: accept % s: % d connect to me.", inet_ntoa (ADDR. sin_addr), ntohs (ADDR. sin_port ));
// Create a UDP socket
S [0] = socket (af_inet, sock_dgram, ipproto_udp );
If (s [0] = invalid_socket)
{
Showerror ("/ntcp2udp: Create UDP socket ");
_ Delsock (s [1]);
Sleep (5000 );
Continue;
}
Bool bindok = false;
Int localtmpport = asi. localtmpport;
If (localtmpport <1) localtmpport = 4000;
While (localtmpport: <65535)
{
// Listen to the address structure of the local UDP port
Udplocal. sin_family = af_inet;
Udplocal. sin_addr.s_addr = inaddr_any;
Udplocal. sin_port = htons (localtmpport );
// Bind UDP socket
Iret = BIND (s [0], (struct sockaddr *) & udplocal, sizeof (udplocal ));
If (iret = socket_error)
{
Printf ("/ntcp2udp: bind UDP port % d failed.", localtmpport );
Localtmpport ++;
Sleep (50 );
Continue;
}
Else
{
Printf ("/ntcp2udp: bind UDP port % d OK.", localtmpport );
Bindok = true;
Break;
}
}
If (! Bindok)
{
_ Delsock (s [0]);
_ Delsock (s [1]);
Sleep (5000 );
Continue;
}
Dataredirdparam * pdrp = new dataredirdparam;
Pdrp-> sock [0] = s [0];
Pdrp-> sock [1] = s [1];
S [0] = 0;
S [1] = 0;
Memcpy (& pdrp-> sinudp, & sinudp, sizeof (sockaddr_in ));
Pdrp-> sinudpisfilled = sinudpisfilled;
DWORD threadid;
Handle hwaitthread = createthread (null, 0, t2uwaitthread, (lpvoid) pdrp, null, & threadid );
Closehandle (hwaitthread );
// Waitforsingleobject (PSI-> hwaitthread, infinite );
Printf ("/n *************** OK! Tcp2udp: do next *******************/n ");
} // End of while
If (slisten! = Invalid_socket) closesocket (slisten );
Return 0;
}
// T2u waiting thread
DWORD winapi t2uwaitthread (lpvoid)
{
Dataredirdparam * pdrp = (dataredirdparam *) lpvoid;
_ Addsock (pdrp-> sock [0]);
_ Addsock (pdrp-> sock [1]);
Handle hthreads [2];
Dword id [2];
Hthreads [0] = createthread (null, 0, tcp2udp, (lpvoid) pdrp, null, & ID [0]);
_ Addthread (hthreads [0]);
Hthreads [1] = createthread (null, 0, udp2tcp, (lpvoid) pdrp, null, & ID [1]);
_ Addthread (hthreads [1]);
DWORD waiter;
Waiter = waitformultipleobjects (2, hthreads, false, infinite );
If (Waiter = wait_object_0)
{
_ Delthread (hthreads [0]);
_ Delsock (pdrp-> sock [0]);
_ Delsock (pdrp-> sock [1]);
Waitforsingleobject (hthreads [1], 2000 );
_ Delthread (hthreads [1]);
} Else if (Waiter = wait_object_0 + 1)
{
_ Delthread (hthreads [1]);
_ Delsock (pdrp-> sock [1]);
_ Delsock (pdrp-> sock [0]);
Waitforsingleobject (hthreads [0], 2000 );
_ Delthread (hthreads [0]);
} Else
{
_ Delsock (pdrp-> sock [1]);
_ Delsock (pdrp-> sock [0]);
_ Delthread (hthreads [1]);
_ Delthread (hthreads [0]);
}
Printf ("/ntcp2udp: Socket closed./N ");
Delete pdrp;
Exitthread (0 );
Return 0;
}
// TCP 2 UDP code
// Read from sock [1] => TCP socket
// Write to sock [0] => UDP socket
DWORD tcp2udp (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; // number of times after UDP fails to send
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 ");
// The number of repeated sending times is reduced by one
If (iudprepeat --)> 0)
{
Printf ("/ntry % d times to send.", iudprepeat );
Continue;
}
}
If (nsendcount <= 0) return 0;
Printf ("/ntcp2udp [% d] sendto % s: % 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;
}
// UDP 2 TCP code
// Write to sock [1] and TCP socket
// Read from sock [0], UDP socket
//
DWORD udp2tcp (lpvoid)
{
Dataredirdparam * tudp = (dataredirdparam *) lpvoid;
Socket * s = tudp-> sock;
DWORD threadid = getcurrentthreadid ();
Printf ("/n *** new udp2tcp % d recvfrom % d send % d./N", threadid, s [0], s [1]);
Char incomingbuff [maxsize];
Struct sockaddr_in from;
Int dwsize = sizeof (from );
Int READ = 1;
While (read> 0)
{
Read = recvfrom (s [0], incomingbuff, maxsize, 0, (sockaddr *) & from, & dwsize );
If (read <= 0) break;
If (tudp-> sinudpisfilled! = True)
{
Tudp-> sinudp. sin_family = af_inet;
Tudp-> sinudp. sin_addr = from. sin_addr;
Tudp-> sinudp. sin_port = from. sin_port;
Tudp-> sinudpisfilled = true;
}
Printf ("/nudp2tcp [% d] recvfrom % s: % d bytes.", threadid, inet_ntoa (from. sin_addr), ntohs (from. sin_port), read );
Int NPOs = 0;
While (NPOs <read)
{
Int nsendcount = Send (s [1], incomingbuff + NPOs, read-NPOs, 0 );
If (nsendcount <= 0) return 0;
Printf ("/nudp2tcp thread % d send % d bytes.", threadid, nsendcount );
NPOs + = nsendcount;
}
}
Printf ("/nudp2tcp % d lasterror % d", threadid, getlasterror ());
Return 0;
}