Connect in UDP Programming

Source: Internet
Author: User
Tags htons
After the standard UDP client has opened a set of interfaces, it generally uses the sendto and recvfrom functions to send data. Recently, we can see that the ntpclient Code uses the direct method of the send function, so we have analyzed it, in the past, UDP sent data in two ways for you to choose from, by the way, UDP connect usage will be clearly explained.
Method 1:
Socket -----> sendto () or recvfrom ()
Method 2:
Socket -----> connect () -----> send () or Recv ()

First, we can see that UDP can also use connect, but what is the difference between the two methods? First, define the four sending functions:
Int send (int s, const void * MSG, size_t Len, int flags );
Int sendto (int s, const void * MSG, size_t Len, int flags,
Const struct sockaddr * To, socklen_t tolen );

Int Recv (int s, void * Buf, size_t Len, int flags );
Int recvfrom (int s, void * Buf, size_t Len, int flags,
Struct sockaddr * From, socklen_t * fromlen );
From their definition, we can see that sendto and recvfrom specify the address when sending and receiving, while send and Recv do not. Then their address is specified there. The answer lies in connect.
Int connect (INT sockfd, const struct sockaddr * serv_addr, socklen_t
Addrlen );
In UDP programming, if you only send data to one address, you can use SEND and Recv to specify their destination addresses using connect before using them. The connect function is used in UDP to check whether the UDP port is opened. The code in ntpclient is as follows:
Struct sockaddr_in sa_dest;
Bzero (char *) sa_dest, sizeof (* sa_dest ));
Sa_dest-> sin_family = af_inet;
If (stuffnetaddr (& (sa_dest-> sin_addr), host ))
Return 1;

Sa_dest-> sin_port = htons (port );

If (connect (USD, (struct sockaddr *) & sa_dest, sizeof (sa_dest) =-1)
{Perror ("Connect"); return 1 ;}

Return 0;

======================================

Unless the set of interfaces are connected, asynchronous errors will not be returned to the UDP set of interfaces. We can indeed call connect for the UDP set of interfaces, but the results are quite different from those of TCP connections: there is no three-way handshake process.

On the contrary, the kernel only checks whether there are known errors (such as a clearly inaccessible destination) and records the IP address and port number of the Peer end (taken from the set of interface address structure passed to connect ), then return to the calling process immediately.

Compared with the default non-connection interfaces, UDP APIs have three changes:
1. We can no longer specify the IP address and port number for the output operation, that is, we do not use sendto, but use write or send instead, any content written to the connected UDP interface is automatically sent to the Protocol address (such as IP address and port number) specified by connect)
2. Instead of using recvfrom to learn the sender of the datagram, we use read, Recv, or recvmsg instead, the data returned by the kernel for the input operation on a connected UDP interface is only the data packets from the Protocol address specified by connect. The destination is the local Protocol address of the connected UDP interface, but it is not the datagram of the negotiated address that the interface was previously connected to. It is not delivered to the interface. In this way, a connected UDP interface is restricted and only one peer can exchange data packets.
3. An asynchronous error is returned to the process of the connected UDP interface.

On the contrary, we have said that a non-connection UDP interface does not receive any asynchronous errors. To call a UDP interface multiple times, a process with a connection UDP interface can be one of the following two purposes:
A. Specify the new IP address and port number;
B. Disconnect the sleeve Interface

The first purpose (that is, to specify a new peer for a connected UDP Interface) is different from the use of connect in the TCP socket port: For the TCP socket interface, connect can only be called once.

To disconnect a connected UDP interface, we set the address cluster member (sin_family) of the interface address structure to af_unspec when we call connect again.
In this case, an eafnosupport error may be returned, but it does not matter.
To disconnect a set of interfaces, the connect process is called on the connected UDP set interface.

======================================

It has the following benefits:
1) when the peer is selected, the kernel will only send the datagram sent from the Peer of the Helper Object to the set interface, so security can be improved in a certain environment;
2) An asynchronous error will be returned. If the peer end is not started, the icmp echo packet corresponding to the packet sent by default will not be sent to the calling process. If connect is used
3) do not disconnect two packets before sending them, improving the efficiency.

Do an experiment and test it.

First get a udp echo server and send all received data packets back:
A @ A-desktop :~ /D/Lab $ cat rollbackserver. cpp
# Include <iostream>
# Include <stdlib. h>
# Include <string. h>
# Include <unistd. h>
# Include <sys/socket. h>
# Include <netinet/in. h>
# Include <ARPA/inet. h>
Using namespace STD;
Int main ()
{
Int socklistener, nmsglen;
Char szbuf [1024];
Struct sockaddr_in addrlistener;
Socklen_t addrlen;
Addrlen = sizeof (struct sockaddr_in );
Bzero (& addrlistener, sizeof (addrlistener ));
Addrlistener. sin_family = af_inet;
Addrlistener. sin_port = htons (8000 );

If (socklistener = socket (af_inet, sock_dgram, 0) =-1)
{
Perror ("error in getting a socket ");
Exit (1 );
}

If (BIND (socklistener, (struct sockaddr *) & addrlistener, sizeof (addrlistener) =-1)
{
Perror ("bind a listener for a socket ");
Exit (2 );
}

Struct sockaddr_in addrclient;
Cout <"Callback Server begin to listen" <Endl;
While (true)
{
Nmsglen = recvfrom (socklistener, szbuf, 1024,0, (struct sockaddr *) & addrclient, & addrlen );
If (nmsglen> 0)
{
Szbuf [nmsglen] = '\ 0 ';
Cout <"send back:" <szbuf <Endl;
Sendto (socklistener, szbuf, nmsglen, 0, (struct sockaddr *) & addrclient, addrlen );
}
}

}

Write a client, bind a port, and then connect to the server. Accept keyboard input at any time and send it to the server. Accept and print the incoming data from the port at any time. If there is no connection, the data sent to this port will be accepted, but what will happen after connect is called?
A-desktop :~ /D/Lab $ cat udpclient. cpp
# Include <iostream>
# Include <stdlib. h>
# Include <string. h>
# Include <unistd. h>
# Include <sys/socket. h>
# Include <netinet/in. h>
# Include <ARPA/inet. h>
# Include <sys/select. h>
Using namespace STD;
Int main ()
{
Int sockclient, nmsglen, nready;
Char szrecv [1024], szsend [1024], szmsg [1024];
Struct sockaddr_in addrserver, addrclient, addrlocal;
Socklen_t addrlen;
Fd_set sethold, settest;

Sockclient = socket (af_inet, sock_dgram, 0 );
Addrlen = sizeof (struct sockaddr_in );
Bzero (& addrserver, sizeof (addrserver ));
Addrserver. sin_family = af_inet;
Addrserver. sin_addr.s_addr = inet_addr ("127.0.0.1 ");
Addrserver. sin_port = htons (8000 );

Addrlocal. sin_family = af_inet; // bind to a local port
Addrlocal. sin_addr.s_addr = htonl (inaddr_any );
Addrlocal. sin_port = htons (9000 );
If (BIND (sockclient, (struct sockaddr *) & addrlocal, sizeof (addrlocal) =-1)
{
Perror ("error in binding ");
Exit (2 );
}

If (connect (sockclient, (struct sockaddr *) & addrserver, sizeof (addrserver) =-1)
{
Perror ("error in connecting ");
Exit (1 );
}

Fd_zero (& sethold );
Fd_set (stdin_fileno, & sethold );
Fd_set (sockclient, & sethold );
Cout <"you can type in sentences any time" <Endl;
While (true)
{
Settest = sethold;
Nready = select (sockclient + 1, & settest, null );
If (fd_isset (0, & settest ))
{
Nmsglen = read (0, szmsg, 1024 );
Write (sockclient, szmsg, nmsglen );
}
If (fd_isset (sockclient, & settest ))
{
Nmsglen = read (sockclient, szrecv, 1024 );
Szrecv [nmsglen] = '\ 0 ';
Cout <"read:" <szrecv <Endl;
}

}

}
Finally, a "third party" sends a datagram to the second port. Check whether she will become a loyal emotional guardian:
A @ A-desktop :~ /D/Lab $ cat clienta. cpp
# Include <string. h>
# Include <iostream>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/socket. h>
# Include <netinet/in. h>
# Include <ARPA/inet. h>
Using namespace STD;
Int main ()
{
Socklen_t addrlen = sizeof (struct sockaddr_in );
Struct sockaddr_in addrserver;
Char szmsg [1024];
Int sockclient;

Addrserver. sin_family = af_inet;
Addrserver. sin_addr.s_addr = inet_addr ("127.0.0.1 ");
Addrserver. sin_port = htons (9000 );

Sockclient = socket (af_inet, sock_dgram, 0 );
While (true)
{
Static int id = 0;
Snprintf (szmsg, sizeof (szmsg), "this is % d", Id ++ );
Sendto (sockclient, szmsg, strlen (szmsg), 0, (struct sockaddr *) & addrserver, sizeof (addrserver ));
Sleep (1 );
}
}

Experiment results:
Run the first program, the third program, and the second program.
Server:

A @ A-desktop :~ /D/Lab $./rollback
Callback Server begin to listen
Send back: xinheblue likes playing

Send back: And listenning to music

The second program:
A @ A-desktop :~ /D/Lab $./udpclient
You can type in sentences any time
Xinheblue likes playing
Read: xinheblue likes playing

And listenning to music
Read: And listenning to music

The implementation result shows that after the second program calls connect, the packet sent by the third program is not discarded.

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.