Problems with UDP Intranet and Internet connection

Source: Internet
Author: User
Tags set socket htons

I have been busy with UDP socket communication over the past few days. After a few days, I have finally achieved some success ....

If you do not understand the differences between the Intranet and the Internet, and do not know the LAN and WAN, you should first familiarize yourself with the program. My current situation is that the client is on an intranet and wants to connect to an internet server. After receiving a request from the client, the Internet Server gives feedback to the client.

Please note that it is UDP, not TCP.

First introduce some tips about Intranet and Internet:

For example, if my Intranet IP address is 192.168.0.2 and the port is 3200, I want to communicate with the Internet IP address 220.120.123.42 and the port is 23654 and initiate a request from the client, you can find the server based on the Internet IP address and port. This is a single communication, but it is difficult for the server to send messages to the Intranet machine. If you do not agree, Please carefully consider it before making a brick.

The path of the entire data stream is as follows:

My Intranet IP address and port will change after passing through my gateway. The gateway's Internet may change to 124.253.124.12: 62145. Actually, the address and port after the gateway is converted to the server, that is to say, only the Gateway knows which machine your intranet IP address and port are. Well, it's much easier to think about it. Let's take a look at the code.

 

For UDP programming, pay attention to the port number of the client. Due to the difference between TCP and UDP, there is no persistent connection or stable communication channel.

 

# Include <winsock2.h>
# Pragma comment (Lib, "ws2_32 ")

// Socket version

Wsadata;
Word socketversion = makeword (2, 2 );
If (: wsastartup (socketversion, & wsadata )! = 0)
{
Trace (L "init socket DLL error! ");
}

// Clientudp. h

PRIVATE:
DWORD mtargetip; // remote IP address (in the byte sequence of the host)
Word mtargetport; // remote port number
Word mlocalport; // local port number
Bool misprocessing ing; // mark of the data being received
Handle mrcvthread; // handle of the Data receiving thread
Socket msckreceiver; // The socket used for receiving
Socket mscksender; // The socket used for sending
PRIVATE:

// Create/destroy the socket used for sending
Bool createsender (void );
Void deletesender (void );
// Create/destroy the socket used for receiving
Bool createreceiver (void );
Void deletereceiver (void );
Void receivingloop (void); // the process of receiving data.
Static DWORD winapi receivingthrd (void * pparam); // receives the thread execution body
// Start/stop the data receiving thread
Bool startreceiving (void );
Void stopreceiving (void );
Void senddata (char * pchar, long length); // sent data (content, length)
Bool gethostinfo (char * outip, char * outname = NULL); get local information

// Clientudp. cpp

Bool createsender (void)
{
// Deletesender ();

Mscksender = socket (af_inet, sock_dgram, 0 );
If (mscksender! = Invalid_socket)
{
Bool flag = true;
Int RETR = setsockopt (mscksender, sol_socket, so_reuseaddr,
(Char *) & flag, sizeof (FLAG); // set socket to address multiplexing
If (RETR = socket_error)
{
Deletereceiver ();
Return false;
}
Int ret = 0;
Sockaddr_in ADDR;
Memset (char *) & ADDR, 0, sizeof (ADDR ));
Char IP [20];
Char name [20];
Gethostinfo (IP, name); // get the IP address and User Name of the Local Machine
ADDR. sin_addr.s_un.s_addr = inet_addr (IP );
ADDR. sin_family = af_inet;
ADDR. sin_port = htons (clientport); // The local port. Note that the port must be the same as the listening port (which will be written below)
Ret = BIND (mscksender, (struct sockaddr *) & ADDR, sizeof (ADDR); // bind the socket to be sent
If (ret = socket_error)
{
Deletesender ();
Return false;
}

Return true;
}
Return false;
}

// Sent data

Void senddata (char * pchar, long length)
{
Char * TT = new char [Length + 1];
Memset (TT, '/0', Length + 1 );
Memcpy (TT, pchar, length );
Sockaddr_in remote;
Memset (char *) & remote, 0, sizeof (remote ));
Remote. sin_addr.s_un.s_addr = inet_addr (ip_server); // the IP address of the server to be sent.
Remote. sin_family = af_inet;
Remote. sin_port = htons (usrport_server); // server port

Sendto (mscksender, TT, length, 0,
(Sockaddr *) & remote, sizeof (remote ));
Deletesender (); // close the sending socket upon each sending. I tested it. If it is commented out, the server will not receive any feedback from the server next time.
Delete [] tt;
}

 

 

Bool gethostinfo (char * outip, char * outname)
{
Char name [300];
If (gethostname (name, 300) = 0)
{
If (outname)
{
Strcpy (outname, name );
}

Phostent hostinfo;
If (hostinfo = gethostbyname (name ))! = NULL)
{
Lpcstr Pip = inet_ntoa (* (struct in_addr *) * hostinfo-> h_addr_list );
Strcpy (outip, pip );
Return true;
}
}
Return false;
}

 

Void deletesender (void)
{
If (mscksender! = Invalid_socket)
{
Closesocket (mscksender );
Mscksender = invalid_socket;
}
}

// Create the received socket

Bool createreceiver (void)
{
Deletereceiver ();
// Create a socket for UDP Transmission
Msckreceiver = socket (af_inet, sock_dgram, 0 );
If (msckreceiver! = Invalid_socket)
{
// Set the parameter on the socket: Allow address multiplexing
Bool flag = true;
Int ret = setsockopt (msckreceiver, sol_socket, so_reuseaddr,
(Char *) & flag, sizeof (FLAG ));
If (ret = socket_error)
{
Deletereceiver ();
Return false;
}
// Bind the socket to the local port number
Sockaddr_in ADDR;
ADDR. sin_family = af_inet;
ADDR. sin_addr.s_addr = htonl (inaddr_any );
ADDR. sin_port = htons (clientport); // you must set the listening port and sending port to the same port.
Ret = BIND (msckreceiver, (struct sockaddr *) & ADDR, sizeof (ADDR ));
If (ret = socket_error)
{
Deletereceiver ();
Return false;
}
Return true;
}

Return false;
}

// Destroy the receiving socket
Void deletereceiver (void)
{
If (msckreceiver! = Invalid_socket)
{
Closesocket (msckreceiver );
Msckreceiver = invalid_socket;
}
}

// Enable the receiving thread
Bool startreceiving (void)
{
// Create socket if necessary
If (msckreceiver = invalid_socket)
{
Createreceiver ();
}

If (msckreceiver! = Invalid_socket)
{
If (misprocessing ing)
{
Return true;
}

DWORD threadid = 0;
Mrcvthread = createthread (null, 0, receivingthrd,
This, 0, & threadid );
Return (mrcvthread! = NULL );
}
Return false;
}
// Thread function execution body: calls the nested ingloop function of this class.
DWORD winapi cudpclient_onedlg: receivingthrd (void * pparam)
{
Assert (pparam );
Cudpclient_onedlg * pcontroller = (cudpclient_onedlg *) pparam;
Pcontroller-> mongoingloop ();
Return 0;
}
// Data receiving process
Void cudpclient_onedlg: receivingloop (void)
{
Struct sockaddr_in addr_cli;
Int addr_cli_len = sizeof (addr_cli );
Char buffer [max_path] = {'/0 '};
Long bytes = 0;
Misconfiguring = true;
Cstring tnote = l "";
// Wait for receiving data
While (misprocessing ing)
{
Int addr_cli_len = sizeof (addr_cli );
Bytes = recvfrom (msckreceiver, (char *) buffer, max_path, 0, (lpsockaddr) & addr_cli, (int *) & addr_cli_len );
If (Bytes = socket_error | bytes = 0)
{
// If the socket fails to be sent or the socket is disconnected, the loop will jump out.
Misconfiguring = false;
}
Else
{
Cedit * Client1 = (cedit *) This-> getdlgitem (idc_edit1 );
Char * pstr = inet_ntoa (addr_cli.sin_addr );

Ptchar pszop = new tchar [strlen (pstr) * 2 + 1];
Memset (pszop, '/0', strlen (pstr) * 2 + 1 );
Multibytetowidechar (cp_acp, 0, (lpcstr) pstr, (INT) strlen (pstr) * 2, pszop, (INT) strlen (pstr) * 2 );

Ptchar pszcontent = new tchar [bytes * 2 + 1];
Memset (pszcontent, '/0', bytes * 2 + 1 );
Multibytetowidechar (cp_acp, 0, (lpcstr) buffer, bytes * 2, pszcontent, bytes * 2 );

Cstring text1;
Text1.format (L "client 1 IP: % s, Port: % d, reply content: % s", pszop, addr_cli.sin_port, pszcontent );
Tnote + = text1 + L "/R/N ";
Client1-> setwindowtext (tnote );

Delete [] pszop;
Delete [] pszcontent;
Memset (buffer, '/0', strlen (buffer ));

}
}
}
Void cudpclient_onedlg: stopreceiving (void)
{
If (misprocessing ing)
{
Deletereceiver ();
// Make sure the processing ing thread has been terminated
If (mrcvthread! = NULL)
{
Waitforsingleobject (mrcvthread, infinite );
Mrcvthread = NULL;
}
}
}

An example of sending a call is as follows:

{

Createsender ();
Char P [] = "Connect ";
Senddata (p, strlen (p ));

}

// Udpserver. h. The method is basically the same as the client

PRIVATE:
// Create/destroy the socket used for receiving
Bool createreceiver (void );
Void deletereceiver (void );
Void receivingloop (void); // the process of receiving data.
Static DWORD winapi receivingthrd (void * pparam); // receives the thread execution body
// Start/stop the data receiving thread
Bool startreceiving (void );
Void stopreceiving (void );

The key here is

Struct sockaddr_in addr_cli;

Bytes = recvfrom (msckreceiver, (char *) buffer, max_path, 0, (lpsockaddr) & addr_cli, (int *) & addr_cli_len );

After receiving the content from the client, the feedback must be:

Sendto (msckreceiver, (char *) buffer, strlen (buffer), 0, (sockaddr *) & addr_cli, sizeof (addr_cli ));

These values should not be modified. If they are fed back to the client as they are, there is no problem. I was planning to send the project back up, but I could not find them to add attachments, So I entered the code, if you do not know, please come and ask me, and I will answer your questions in time.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.