7. UDP
In the most common sense, the so-called UDP is a network protocol that does not matter when it is sent out. Therefore, the sending end of UDP programming only needs to send, and the network connection status does not need to be checked. The following example describes how to write UDP and describes each API and Data Type in detail.
7.1 UDP broadcast sending program
The following is an example of using UDP to send broadcast packets.
# Include <winsock2.h>
# Include <iostream. h>
Void main ()
{
Socket sock; // Socket socket
Char szmsg [] = "this is a UDP test package"; // sent Field
// 1. Start the socket library, version 2.0
Word wversionrequested;
Wsadata;
Int err;
Wversionrequested = makeword (2, 0 );
Err = wsastartup (wversionrequested, & wsadata );
If (0! = ERR) // check whether socket Initialization is successful
{
Cout <"socket2.0 initialization failed, exit! ";
Return;
}
// Check whether the socket library version is 2.0
If (lobyte (wsadata. wversion )! = 2 | hibyte (wsadata. wversion )! = 0)
{
Wsacleanup ();
Return;
}
// 2. Create a socket,
Sock = socket (
Af_inet, // Internetwork: UDP, TCP, etc
Sock_dgram, // _dgram indicates the UDP type.
0 // Protocol
);
If (invalid_socket = sock ){
Cout <"socket creation failed, exit! ";
Return;
}
// 3. Set the socket to the broadcast type,
Bool opt = true;
Setsockopt (sock, sol_socket, so_broadcast, reinterpret_cast <char far *> (& OPT), sizeof (OPT ));
// 4. Set the destination address
Sockaddr_in addrto; // address to which the object is sent
Memset (& addrto, 0, sizeof (addrto ));
Addrto. sin_family = af_inet; // The Address type is Internetwork.
Addrto. sin_addr.s_addr = inaddr_broadcast; // set the IP address to the broadcast address.
Addrto. sin_port = htons (7861); // The port number is 7861.
Int nlen = sizeof (addrto );
Unsigned int uindex = 1;
While (true)
{
Sleep (1000); // The program sleeps for one second.
// Send a message to the broadcast address
If (sendto (sock, szmsg, strlen (szmsg), 0, (sockaddr *) & addrto, nlen)
= Socket_error)
Cout <wsagetlasterror () <Endl;
Else
Cout <uindex ++ <": An UDP package is sended." <Endl;
}
If (! Closesocket (sock) // closes the socket
{
Wsagetlasterror ();
Return;
}
If (! Wsacleanup () // close the socket Library
{
Wsagetlasterror ();
Return;
}
}
Compile command:
CL/C udp_send_broadcast.cpp
Link command (Note that if the library cannot be found, add the path of the database to the/libpath parameter below ):
Link udp_send_broadcast.obj ws2_32.lib
Run the following command:
D: "code" finished code "socket" socket_src> udp_send_broadcast.exe
1: An UDP package is sended.
2: An UDP package is sended.
3: An UDP package is sended.
4: An UDP package is sended.
^ C
The following describes the data types and API functions in the code. If you are patient, you can take a closer look and write programs without patience.
7.2 socket type
Socket is a Socket socket type, which is defined as follows in winsock2.h:
Typedef unsigned int u_int;
Typedef u_int socket;
It can be seen that a socket is actually an unsigned integer and will be managed and used by the socket environment. The socket is created, set, used to send and receive data, and closed.
7.3 word type, makeword, lobyte, and hibyte macros
The word type is a 16-bit unsigned integer, which is defined in wtypes. h:
Typedef unsigned short word;
The purpose is to provide two bytes of storage. In the socket, these two bytes can represent the primary and secondary versions. You can use makeword macros to assign values to a word type. For example, to indicate the major version 2 and minor version 0, you can use the following code:
Word wversionrequested;
Wversionrequested = makeword (2, 0 );
Note that the primary version number 2 of the low-level memory storage is 0 and the secondary version number of the High-level memory storage is 0x0002. The macro lobyte can be used to read the low byte of word, and the hibyte can read the high byte.
7.4 wsadata and lpwsadata
The wsadata type is a structure that describes some information about the socket library. Its structure is defined as follows:
Typedef struct wsadata {
Word wversion;
Word whighversion;
Char szdescription [wsadescription_len + 1];
Char szsystemstatus [wsasys_status_len + 1];
Unsigned short imaxsockets;
Unsigned short imaxudpdg;
Char far * lpvendorinfo;
} Wsadata;
Typedef wsadata far * lpwsadata;
It is worth noting that the wversion field stores the socket version type. Lpwsadata is the pointer type of wsadata. They are read through the socket initialization function wsastartup without being manually entered by programmers.
7.5 wsastartup Function
The wsastartup function is used to initialize the socket environment. Its definition is as follows:
Int Pascal far wsastartup (word wversionrequired, lpwsadata );
The return value is an integer and the call method is Pascal (standard type, Pascal equals _ stdcall). There are two parameters. The first parameter is of the Word type and specifies the socket version number, the second parameter is a pointer of the wsadata type.
If the returned value is 0, the initialization is successful. If the value is not 0, the initialization fails.
7.6 wsacleanup Function
This is the exit function of the socket environment. If the returned value is 0, it indicates success, and socket_error indicates failure.
7.7 socket Functions
Socket creation function, which is defined:
Socket Pascal far socket (int af, int type, int Protocol );
The first parameter is int AF, indicating the network address family. Currently, only af_inet is valid, indicating the Internet address family;
The second parameter is int type, indicating the network protocol type. sock_dgram indicates UDP protocol and sock_stream indicates TCP protocol;
The third parameter is int protocol, which specifies the Special Protocol of the network address family. Currently, it is useless. assign a value of 0.
The returned value is socket. If invalid_socket is returned, it fails.
7.8 setsockopt Function
This function is used to set the socket attribute. If the socket attribute cannot be set correctly, data transmission and receiving will fail. Definition:
Int Pascal far setsockopt (socket S, int level, int optname,
Const char far * optval, int optlen );
The return value is of the int type. 0 indicates success, and socket_error indicates an error occurs.
The first parameter socket s represents the socket to be set;
The second parameter, int level, indicates the level of the property to be set. The level includes the following values: sol_socket indicates the socket level; ipproto_tcp indicates the TCP protocol level, ipproto_ip indicates the IP protocol level (I have never used the other two );
The third parameter, int optname, indicates the parameter name. so_broadcast indicates the attribute that allows sending broadcast data. For other attributes, see msdn;
The fourth parameter const char far * optval indicates the pointer to the value stored in the parameter. Note that reinterpret_cast type conversion may be used here;
The fifth parameter, int optlen, represents the length of the stored parameter value variable.
7.9 sockaddr_in, in_addr type, inet_addr, inet_ntoa Function
Sockaddr_in defines the address for sending and receiving data packets through a socket, and defines:
Struct sockaddr_in {
Short sin_family;
U_short sin_port;
Struct in_addr sin_addr;
Char sin_zero [8];
};
The definition of in_addr is as follows:
Struct in_addr {
Union {
Struct {u_char s_b1, s_b2, s_b3, s_b4;} s_un_ B;
Struct {u_short s_w1, s_w2;} s_un_w;
U_long s_addr;
} S_un;
First, describe the meaning of in_addr. Obviously, it is a consortium that stores IP addresses (if you forget the meaning of union, see C ++). There are three expressions:
First, four bytes are used to represent the four numbers of IP addresses;
The second type uses two dual-byte pairs to represent IP addresses;
The third is to use a long integer to represent the IP address.
One of the simplest ways to assign values to in_addr is to use the inet_addr function, which can convert a string value representing an IP address to the in_addr type, as shown in
Addrto. sin_addr.s_addr = inet_addr ("192.168.0.2 ");
This function is not used in this example because it is a broadcast address. The inverse function is inet_ntoa. You can convert an in_addr type into a string.
The meaning of sockaddr_in is more extensive than that of in_addr. the meanings and values of each field are as follows:
The first field, short sin_family, represents the network address family. As described above, only the value af_inet can be set;
The second field u_short sin_port represents the IP address port, which is specified by the programmer;
The third field, struct in_addr sin_addr, represents the IP address;
The fourth field is Char sin_zero [8]. It is funny to ensure that the length of sockaddr_in is equal to that of sockaddr.
The following indicates a broadcast address with the port number 7861:
Sockaddr_in addrto; // address to which the object is sent
Memset (& addrto, 0, sizeof (addrto ));
Addrto. sin_family = af_inet; // The Address type is Internetwork.
Addrto. sin_addr.s_addr = inaddr_broadcast; // set the IP address to the broadcast address.
Addrto. sin_port = htons (7861); // The port number is 7861.
7.10 sockaddr type
The sockaddr type is used to indicate the socket address type. Compared with the sockaddr_in Type above, sockaddr is applicable to a wider range, because sockaddr_in is only applicable to TCP/IP addresses. The definition of sockaddr is as follows:
Struct sockaddr {
U_short sa_family;
Char sa_data [14];
};
It can be seen that sockaddr has 16 bytes, while sockaddr_in also has 16 bytes. Therefore, sockaddr_in can be forcibly converted to sockaddr. In fact, this method is often used.
7.11 sleep Functions
Indicates that the thread is suspended for a period of time. Sleep (1000) indicates that a second is suspended. It is defined in the WINBASE. h header file. WINBASE. H is included in windows. H, and Windows. H is included in winsock2.h. Therefore, the sleep function in this example does not need to contain other header files.
7.12 sendto Function
There are two sets of sending and receiving functions in the socket: sendto and recvfrom; and send and Recv. The first set must specify the address in the function parameters. The second set must first bind the socket with an address, and then send and receive the address directly without binding the address. Sendto is defined as follows:
Int Pascal far sendto (socket S, const char far * Buf, int Len, int flags, const struct sockaddr far * To, int tolen );
The first parameter is socket;
The second parameter is the data pointer to be transmitted;
The third parameter is the length of data to be transmitted (in bytes );
The fourth parameter is the transfer method identifier. If you do not need special requirements, you can set it to 0. For other values, see msdn;
The fifth parameter is the target address. Note that the sockaddr pointer is used here;
The sixth parameter is the address length;
The return value is an integer. If the request succeeds, the number of bytes are returned. If the request fails, socket_error is returned.
7.13 wsagetlasterror Function
This function is used to read error codes after the socket-related API fails. Based on these error codes, you can check the cause of the error.
7.14 closesocket
Close the socket. Its parameter is socket type. 0 is returned for success, and socket_error is returned for failure.
8. TCP
The biggest difference between TCP and UDP is that TCP is a connection-oriented protocol. TCP must be connected before sending and receiving data, and this connection must be maintained during sending and receiving.
The sender's steps are as follows (initialization and shutdown of the socket environment are omitted ):
1. Use the socket function to create a socket sock;
2. Bind sock to a local address;
3. Listen to sock socket with listen;
4. Use the accept function to receive the client connection and return the client socket;
5. Use send to send data on the client socket;
6. Use the closesocket function to close socket sock and clientsocket;
The procedure of the receiver is as follows:
1. Use the socket function to create a socket sock;
2. Create a remote address pointing to the service provider;
3. Connect sock to the service provider using a remote address;
4. Use Recv on the socket to receive data;
5. Use the closesocket function to disable socket sock;
It is worth noting that the service provider has two addresses: The local address myaddr and the target address addrto. The local address myaddr is used to bind the local socket sock, and the target address is used by sock to access the client socket clientsocket. In this way, sock and clientsocket are connected successfully, and the two addresses are also connected. When the service provider uses clientsocket to send data, the data is transmitted from the local address to the target address.
The customer has only one address, that is, the source address addrfrom. This address is used to connect a remote service provider socket. If connect succeeds, the local socket is connected to the remote source address. Therefore, this socket can be used to receive remote data. In fact, the client socket has been implicitly bound to the local address, so you do not need to explicitly call the BIND function, even if it is called, it will not produce results.
For specific source code, see tcp_send.cpp and tcp_recv.cpp. Change the IP address in the source code to an IP address that meets your needs. To reduce Code complexity, the code for reading the IP address of the local machine is not used. This function code will be included in subsequent examples.
8.1 bind Functions
The BIND function is used to bind a socket to an IP address. Generally, it is called only by the service provider (that is, the data sender). Many functions call the BIND function implicitly.
8.2 listen Function
The slave server listens to the client's connection. The same socket can be monitored multiple times.
8.3 connect and accept Functions
Connect is the function of the client to connect to the service provider, and accept is the function that the service provider agrees to connect to the client. These two functions can send and receive data after they are successfully called in their respective programs.
8.4 send and Recv Functions
Send and Recv are two important functions used to send and receive data. Send can only be used in the connected state, while Recv can be used in the connected and non-connected state.
The definition of send is as follows:
Int wsaapi send (
Socket s,
Const char far * Buf,
Int Len,
Int flags
);
The parameter meanings are the same as those of the first four parameters in sendto. The Recv is defined as follows:
Int wsaapi Recv (
Socket s,
Char far * Buf,
Int Len,
Int flags
);
The parameter meanings are the same as those in send.