当前位置:网站首页>【WinSock】TCP UDP Boardcast Multicast
【WinSock】TCP UDP Boardcast Multicast
2022-07-23 08:43:00 【zhy29563】
Catalog
1. Auxiliary function (common.h)
#ifndef CPP_NETWORK_COMMUNICATION_COMMON_H
#define CPP_NETWORK_COMMUNICATION_COMMON_H
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <cstdio>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#define INTERFACE_ADDRESS "127.0.0.1"
#define MULTICAST_ADDRESS "239.127.3.5"
#define MULTICAST_PORT 7667
#define BUFFER_SIZE (1024)
#define TCP_SERVER_PORT (8000)
#define TCP_Client_PORT (8001)
#define UDP_SERVER_PORT (7667)
#define UDP_CLIENT_PORT (7668)
#define COUNT (5)
#ifdef DEBUG
#define DEBUG_FUNCTION_NAME() \ {
\ printf("================================================================\n"); \ printf("%s\n", __func__); \ }
#define DEBUG_LOG(format, ...) \ {
\ printf("LOG:[%s:%d->%s] " format, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }
#else
#define DEBUG_FUNCTION_NAME()
#define DEBUG_LOG(format, ...)
#endif
void show_error_code()
{
int error_code = WSAGetLastError();
switch (error_code)
{
case 0:
std::cout << "ERROR CODE (" << error_code << " ): SUCCESS" << std::endl;
break;
case WSA_INVALID_HANDLE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_INVALID_HANDLE" << std::endl;
break;
case WSA_NOT_ENOUGH_MEMORY:
std::cout << "ERROR CODE (" << error_code << " ): WSA_NOT_ENOUGH_MEMORY" << std::endl;
break;
case WSA_INVALID_PARAMETER:
std::cout << "ERROR CODE (" << error_code << " ): WSA_INVALID_PARAMETER" << std::endl;
break;
case WSA_OPERATION_ABORTED:
std::cout << "ERROR CODE (" << error_code << " ): WSA_OPERATION_ABORTED" << std::endl;
break;
case WSA_IO_INCOMPLETE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_IO_INCOMPLETE" << std::endl;
break;
case WSA_IO_PENDING:
std::cout << "ERROR CODE (" << error_code << " ): WSA_IO_PENDING" << std::endl;
break;
case WSAEINTR:
std::cout << "ERROR CODE (" << error_code << " ): WSAEINTR" << std::endl;
break;
case WSAEBADF:
std::cout << "ERROR CODE (" << error_code << " ): WSAEBADF" << std::endl;
break;
case WSAEACCES:
std::cout << "ERROR CODE (" << error_code << " ): WSAEACCES" << std::endl;
break;
case WSAEFAULT:
std::cout << "ERROR CODE (" << error_code << " ): WSAEFAULT" << std::endl;
break;
case WSAEINVAL:
std::cout << "ERROR CODE (" << error_code << " ): WSAEINVAL" << std::endl;
break;
case WSAEMFILE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEMFILE" << std::endl;
break;
case WSAEWOULDBLOCK:
std::cout << "ERROR CODE (" << error_code << " ): WSAEWOULDBLOCK" << std::endl;
break;
case WSAEINPROGRESS:
std::cout << "ERROR CODE (" << error_code << " ): WSAEINPROGRESS" << std::endl;
break;
case WSAEALREADY:
std::cout << "ERROR CODE (" << error_code << " ): WSAEALREADY" << std::endl;
break;
case WSAENOTSOCK:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOTSOCK" << std::endl;
break;
case WSAEDESTADDRREQ:
std::cout << "ERROR CODE (" << error_code << " ): WSAEDESTADDRREQ" << std::endl;
break;
case WSAEMSGSIZE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEMSGSIZE" << std::endl;
break;
case WSAEPROTOTYPE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEPROTOTYPE" << std::endl;
break;
case WSAENOPROTOOPT:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOPROTOOPT" << std::endl;
break;
case WSAEPROTONOSUPPORT:
std::cout << "ERROR CODE (" << error_code << " ): WSAEPROTONOSUPPORT" << std::endl;
break;
case WSAESOCKTNOSUPPORT:
std::cout << "ERROR CODE (" << error_code << " ): WSAESOCKTNOSUPPORT" << std::endl;
break;
case WSAEOPNOTSUPP:
std::cout << "ERROR CODE (" << error_code << " ): WSAEOPNOTSUPP" << std::endl;
break;
case WSAEADDRINUSE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEADDRINUSE" << std::endl;
break;
case WSAEADDRNOTAVAIL:
std::cout << "ERROR CODE (" << error_code << " ): WSAEADDRNOTAVAIL" << std::endl;
break;
case WSAENETDOWN:
std::cout << "ERROR CODE (" << error_code << " ): WSAENETDOWN" << std::endl;
break;
case WSAENETUNREACH:
std::cout << "ERROR CODE (" << error_code << " ): WSAENETUNREACH" << std::endl;
break;
case WSAENETRESET:
std::cout << "ERROR CODE (" << error_code << " ): WSAENETRESET" << std::endl;
break;
case WSAECONNABORTED:
std::cout << "ERROR CODE (" << error_code << " ): WSAECONNABORTED" << std::endl;
break;
case WSAECONNRESET:
std::cout << "ERROR CODE (" << error_code << " ): WSAECONNRESET" << std::endl;
break;
case WSAENOBUFS:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOBUFS" << std::endl;
break;
case WSAEISCONN:
std::cout << "ERROR CODE (" << error_code << " ): WSAEISCONN" << std::endl;
break;
case WSAENOTCONN:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOTCONN" << std::endl;
break;
case WSAESHUTDOWN:
std::cout << "ERROR CODE (" << error_code << " ): WSAESHUTDOWN" << std::endl;
break;
case WSAETOOMANYREFS:
std::cout << "ERROR CODE (" << error_code << " ): WSAETOOMANYREFS" << std::endl;
break;
case WSAETIMEDOUT:
std::cout << "ERROR CODE (" << error_code << " ): WSAETIMEDOUT" << std::endl;
break;
case WSAECONNREFUSED:
std::cout << "ERROR CODE (" << error_code << " ): WSAECONNREFUSED" << std::endl;
break;
case WSAELOOP:
std::cout << "ERROR CODE (" << error_code << " ): WSAELOOP" << std::endl;
break;
case WSAENAMETOOLONG:
std::cout << "ERROR CODE (" << error_code << " ): WSAENAMETOOLONG" << std::endl;
break;
case WSAEHOSTDOWN:
std::cout << "ERROR CODE (" << error_code << " ): WSAEHOSTDOWN" << std::endl;
break;
case WSAEHOSTUNREACH:
std::cout << "ERROR CODE (" << error_code << " ): WSAEHOSTUNREACH" << std::endl;
break;
case WSAENOTEMPTY:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOTEMPTY" << std::endl;
break;
case WSAEPROCLIM:
std::cout << "ERROR CODE (" << error_code << " ): WSAEPROCLIM" << std::endl;
break;
case WSAEUSERS:
std::cout << "ERROR CODE (" << error_code << " ): WSAEUSERS" << std::endl;
break;
case WSAEDQUOT:
std::cout << "ERROR CODE (" << error_code << " ): WSAEDQUOT" << std::endl;
break;
case WSAESTALE:
std::cout << "ERROR CODE (" << error_code << " ): WSAESTALE" << std::endl;
break;
case WSAEREMOTE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEREMOTE" << std::endl;
break;
case WSASYSNOTREADY:
std::cout << "ERROR CODE (" << error_code << " ): WSASYSNOTREADY" << std::endl;
break;
case WSAVERNOTSUPPORTED:
std::cout << "ERROR CODE (" << error_code << " ): WSAVERNOTSUPPORTED" << std::endl;
break;
case WSANOTINITIALISED:
std::cout << "ERROR CODE (" << error_code << " ): WSANOTINITIALISED" << std::endl;
break;
case WSAEDISCON:
std::cout << "ERROR CODE (" << error_code << " ): WSAEDISCON" << std::endl;
break;
case WSAENOMORE:
std::cout << "ERROR CODE (" << error_code << " ): WSAENOMORE" << std::endl;
break;
case WSAECANCELLED:
std::cout << "ERROR CODE (" << error_code << " ): WSAECANCELLED" << std::endl;
break;
case WSAEINVALIDPROCTABLE:
std::cout << "ERROR CODE (" << error_code << " ): WSAEINVALIDPROCTABLE" << std::endl;
break;
case WSAEINVALIDPROVIDER:
std::cout << "ERROR CODE (" << error_code << " ): WSAEINVALIDPROVIDER" << std::endl;
break;
case WSAEPROVIDERFAILEDINIT:
std::cout << "ERROR CODE (" << error_code << " ): WSAEPROVIDERFAILEDINIT" << std::endl;
break;
case WSASYSCALLFAILURE:
std::cout << "ERROR CODE (" << error_code << " ): WSASYSCALLFAILURE" << std::endl;
break;
case WSASERVICE_NOT_FOUND:
std::cout << "ERROR CODE (" << error_code << " ): WSASERVICE_NOT_FOUND" << std::endl;
break;
case WSATYPE_NOT_FOUND:
std::cout << "ERROR CODE (" << error_code << " ): WSATYPE_NOT_FOUND" << std::endl;
break;
case WSA_E_NO_MORE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_E_NO_MORE" << std::endl;
break;
case WSA_E_CANCELLED:
std::cout << "ERROR CODE (" << error_code << " ): WSA_E_CANCELLED" << std::endl;
break;
case WSAEREFUSED:
std::cout << "ERROR CODE (" << error_code << " ): WSAEREFUSED" << std::endl;
break;
case WSAHOST_NOT_FOUND:
std::cout << "ERROR CODE (" << error_code << " ): WSAHOST_NOT_FOUND" << std::endl;
break;
case WSATRY_AGAIN:
std::cout << "ERROR CODE (" << error_code << " ): WSATRY_AGAIN" << std::endl;
break;
case WSANO_RECOVERY:
std::cout << "ERROR CODE (" << error_code << " ): WSANO_RECOVERY" << std::endl;
break;
case WSANO_DATA:
std::cout << "ERROR CODE (" << error_code << " ): WSANO_DATA" << std::endl;
break;
case WSA_QOS_RECEIVERS:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_RECEIVERS" << std::endl;
break;
case WSA_QOS_SENDERS:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_SENDERS" << std::endl;
break;
case WSA_QOS_NO_SENDERS:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_NO_SENDERS" << std::endl;
break;
case WSA_QOS_NO_RECEIVERS:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_NO_RECEIVERS" << std::endl;
break;
case WSA_QOS_REQUEST_CONFIRMED:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_REQUEST_CONFIRMED" << std::endl;
break;
case WSA_QOS_ADMISSION_FAILURE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_ADMISSION_FAILURE" << std::endl;
break;
case WSA_QOS_POLICY_FAILURE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_POLICY_FAILURE" << std::endl;
break;
case WSA_QOS_BAD_STYLE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_BAD_STYLE" << std::endl;
break;
case WSA_QOS_BAD_OBJECT:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_BAD_OBJECT" << std::endl;
break;
case WSA_QOS_TRAFFIC_CTRL_ERROR:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_TRAFFIC_CTRL_ERROR" << std::endl;
break;
case WSA_QOS_GENERIC_ERROR:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_GENERIC_ERROR" << std::endl;
break;
case WSA_QOS_ESERVICETYPE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_ESERVICETYPE" << std::endl;
break;
case WSA_QOS_EFLOWSPEC:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFLOWSPEC" << std::endl;
break;
case WSA_QOS_EPROVSPECBUF:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EPROVSPECBUF" << std::endl;
break;
case WSA_QOS_EFILTERSTYLE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFILTERSTYLE" << std::endl;
break;
case WSA_QOS_EFILTERTYPE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFILTERTYPE" << std::endl;
break;
case WSA_QOS_EFILTERCOUNT:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFILTERCOUNT" << std::endl;
break;
case WSA_QOS_EOBJLENGTH:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EOBJLENGTH" << std::endl;
break;
case WSA_QOS_EFLOWCOUNT:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFLOWCOUNT" << std::endl;
break;
case WSA_QOS_EUNKOWNPSOBJ:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EUNKOWNPSOBJ" << std::endl;
break;
case WSA_QOS_EPOLICYOBJ:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EPOLICYOBJ" << std::endl;
break;
case WSA_QOS_EFLOWDESC:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EFLOWDESC" << std::endl;
break;
case WSA_QOS_EPSFLOWSPEC:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EPSFLOWSPEC" << std::endl;
break;
case WSA_QOS_EPSFILTERSPEC:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_EPSFILTERSPEC" << std::endl;
break;
case WSA_QOS_ESDMODEOBJ:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_ESDMODEOBJ" << std::endl;
break;
case WSA_QOS_ESHAPERATEOBJ:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_ESHAPERATEOBJ" << std::endl;
break;
case WSA_QOS_RESERVED_PETYPE:
std::cout << "ERROR CODE (" << error_code << " ): WSA_QOS_RESERVED_PETYPE" << std::endl;
break;
default:
std::cout << "ERROR CODE (" << error_code << " ): Undefined" << std::endl;
break;
}
}
int release()
{
DEBUG_FUNCTION_NAME()
/// int WSACleanup();
/// The operation is successful, and the return value is 0;
/// Otherwise, the return value is SOCKET_ERROR, You can call WSAGetLastError Get the error code
///
/// In a multithreaded environment ,WSACleanup() Aborted Windows Sockets Operations on all threads
if (WSACleanup())
{
show_error_code();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int init(WSADATA &wsaData)
{
DEBUG_FUNCTION_NAME()
/// WSAStartup (WSA yes Windows Sockets API Abbreviation )
/// This function must use WSA The first function called when , For initialization WSA
///
/// int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
/// wVersionRequested
/// Specify what is available to the caller Windows Sockets The highest version of the standard . The high byte specifies the small version ( Revision ) Number , The low byte specifies the major version number
/// lpWSAData
/// Point to WSADATA Pointer to data structure , For reception Windows Sockets Implementation details
/// struct WSAData
/// {
/// WORD wVersion;
/// WORD wHighVersion;
/// unsigned short iMaxSockets;
/// unsigned short iMaxUdpDg;
/// char FAR* lpVendorInfo;
/// char szDescription[WSADESCRIPTION_LEN + 1];
/// char szSystemStatus[WSASYS_STATUS_LEN + 1];
/// }
/// wVersion:
/// Ws2_32.dll The library expects to call the Windows Sockets Standard version . The high byte specifies the small version ( Revision ) Number , The low byte specifies the major version number
/// wHighVersion:
/// Ws2_32.dll Library supported Windows Sockets The highest version of the standard
/// iMaxSockets:
/// Can open SOCKET Maximum number of . The parameter is in WinSock2 And later versions are ignored
/// iMaxUdpDg:
/// Maximum length of data message . The parameter is in WinSock2 And later versions are ignored
/// lpVendorInfo
/// Manufacturer information pointer . The parameter is in WinSock2 And later versions are ignored
/// szDescription
/// With NULL The end of ASCII character string , instructions Windows Sockets Description of the implementation .
/// szSystemStatus:
/// With NULL The end of ASCII character string , instructions Windows Sockets Status or configuration information
auto wVersionRequested = MAKEWORD(2, 2);
int major_version = LOBYTE(wVersionRequested);
int minor_version = HIBYTE(wVersionRequested);
std::cout << "Expected Major Version: " << major_version << std::endl;
std::cout << "Expected Minor Version: " << minor_version << std::endl;
int error_code = WSAStartup(wVersionRequested, &wsaData);
if (error_code)
{
printf("WSAStartup failed with error: %d\n", error_code);
return EXIT_FAILURE;
}
else
{
major_version = LOBYTE(wsaData.wVersion);
minor_version = HIBYTE(wsaData.wVersion);
std::cout << "Used Major Version: " << major_version << std::endl;
std::cout << "Used Minor Version: " << minor_version << std::endl;
major_version = LOBYTE(wsaData.wHighVersion);
minor_version = HIBYTE(wsaData.wHighVersion);
std::cout << "High Major Version: " << major_version << std::endl;
std::cout << "High Minor Version: " << minor_version << std::endl;
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("Could not find a usable version of Winsock.dll\n");
release();
return EXIT_FAILURE;
}
printf("The Winsock 2.2 dll was found okay\n");
}
return EXIT_SUCCESS;
}
int get_host_name()
{
DEBUG_FUNCTION_NAME()
/// int gethostname([out] char *name, [in] int namelen);
/// Get the host name .
/// If no error occurs , return 0;
/// Otherwise return to SOCKET_ERROR, And through WSAGetLastError Get a specific error code .
/// Be careful :
/// 1. The returned host name is in null For the Terminator
/// 2. The length of the host name string must be less than or equal to 256
char host_name[256]{
0};
if (SOCKET_ERROR == gethostname(host_name, 256))
{
show_error_code();
release();
return EXIT_FAILURE;
}
else
{
std::cout << "host name: " << host_name << std::endl;
}
return EXIT_SUCCESS;
}
int create_socket(SOCKET &local_socket, int type)
{
DEBUG_FUNCTION_NAME()
/// SOCKET WSAAPI socket([in] int af, [in] int type, [in] int protocol);
/// Create according to the given transport protocol SOCKET
/// Parameters
/// af: Address family , The common one is AF_INET, AF_INET6
/// type: SOCKET type :
/// SOCK_STREAM TCP
/// SOCK_DGRAM UDP
/// SOCK_RAW Other protocols can be implemented
/// protocol:
/// When the type is specified as SOCK_STREAM or SOCK_DGRAM, This parameter is ignored . When using SOCK_RAW when , The parameter must be specified . The possible values are as follows :
/// IPPROTO_ICMP
/// IPPROTO_IGMP
/// BTHPROTO_RFCOMM
/// IPPROTO_TCP
/// IPPROTO_UDP
/// IPPROTO_ICMPV6
/// IPPROTO_RM
/// Return value
/// No error occurred , Return to one SOCKET The descriptor .
/// Otherwise return to INVALID_SOCKET, You can use WSAGetLastError() Get a specific error code .
local_socket = socket(AF_INET, type, 0);
if (!(local_socket == INVALID_SOCKET))
return EXIT_SUCCESS;
show_error_code();
release();
return EXIT_FAILURE;
}
int bind_local(SOCKET &socket_server, ADDRESS_FAMILY family, ULONG in_addr, USHORT port)
{
DEBUG_FUNCTION_NAME()
/// int WSAAPI bind([in] SOCKET s, [in] const sockaddr *name, [in] int namelen);
/// Bind local information to SOCKET The descriptor
/// Parameters
/// s SOCKET The descriptor
/// name Local address information
/// If name->sin_addr.s_addr The assignment is htonl(INADDR_ANY), Then bind all available of the current host IP
/// If name->sin_addr.s_addr inet_addr("127.0.0.1"), Only the specified IP Address initiated connection or sent data
/// namelen Length of local address information
/// Return value
/// No error occurred , return 0;
/// otherwise , return SOCKET_ERROR, You can use WSAGetLastError() Get a specific error code .
/// u_long WSAAPI htonl (u_long hostlong);
/// u_short WSAAPI ntohs (u_short netshort);
/// Set the value of parameter type , Convert from host byte order to TCP/IP Network byte order
SOCKADDR_IN local_addr;
memset(&local_addr, 0, sizeof(local_addr)); // A choice
ZeroMemory(&local_addr, sizeof(local_addr)); // A choice
local_addr.sin_family = family;
local_addr.sin_addr.s_addr = in_addr;
local_addr.sin_port = htons(port);
if (bind(socket_server, (SOCKADDR *)&local_addr, sizeof(local_addr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int connect_to_server(SOCKET &socket_client, ADDRESS_FAMILY family, ULONG in_addr, USHORT port)
{
DEBUG_FUNCTION_NAME()
/// int WSAAPI connect([in] SOCKET s, [in] const sockaddr *name, [in] int namelen);
/// This function is used to create a connection with the specified external port .
/// Parameters
/// s To be connected SOCKET The descriptor
/// name Remote address information to be connected , If the address fields in the structure are all zero , Will return WSAEADDENOTAVAIL
/// namelen Length of address information
/// Be careful
/// If before calling this function , No local address binding , Then the system will automatically associate a local unique address information , And set SOCKET Is bound .
/// Return value
/// No error occurred , return 0
/// Otherwise return to SOCKET_ERROR, A specific error code , It can be done by WSAGetLastError() To get
SOCKADDR_IN remote_addr;
memset(&remote_addr, 0, sizeof(remote_addr)); // A choice
ZeroMemory(&remote_addr, sizeof(remote_addr)); // A choice
remote_addr.sin_family = family;
remote_addr.sin_addr.s_addr = in_addr;
remote_addr.sin_port = htons(port);
if (connect(socket_client, (SOCKADDR *)&remote_addr, sizeof(remote_addr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int start_listen(SOCKET &socket_server)
{
DEBUG_FUNCTION_NAME()
/// int WSAAPI listen([in] SOCKET s, [in] int backlog);
/// Turn on monitoring
/// Parameters
/// s SOCKET The descriptor
/// backlog The maximum length of the pending connection queue .
/// If set to SOMAXCONN, be responsible for socket The underlying service provider will backlog Set to the maximum reasonable value .
/// If set to SOMAXCONN_HINT(N)( among N It's a number ), be backlog Will be for N, Adjust to range (200, 65535).
/// Please note that ,SOMAXCONN_HINT Can be used for backlog Set to ratio SOMAXCONN Greater value .
/// SOMAXCONN_HINT Receive only Microsoft TCP/IP Service provider support . Not obtained backlog Value standard .
/// Return value
/// No error occurred , return 0;
/// otherwise , return SOCKET_ERROR, You can use WSAGetLastError() Get a specific error code .
if (listen(socket_server, 5))
{
show_error_code();
release();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int wait_connect(SOCKET &socket_server, SOCKET &socket_client)
{
DEBUG_FUNCTION_NAME()
/// SOCKET WSAAPI accept([in] SOCKET s, [out] sockaddr *addr, [in, out] int *addrlen);
/// Wait for the client to connect
/// Parameters
/// s SOCKET The descriptor
/// addr Connected client address information
addrlen The length of the connected client address information
/// Return value
/// No error occurred , Returns the... Of the connected client SOCKET The descriptor ,
/// Otherwise return to INVALID_SOCKET, You can use WSAGetLastError() Get a specific error code .
SOCKADDR_IN client_addr{
0};
int len = sizeof(SOCKADDR);
memset(&client_addr, 0, len);
socket_client = accept(socket_server, (SOCKADDR *)&client_addr, &len);
if (INVALID_SOCKET == socket_client)
{
show_error_code();
release();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int recv_message(SOCKET &socket_client, char *buffer, int &recv_length)
{
DEBUG_FUNCTION_NAME()
/// No mistake , Returns the length of the received string . If the connection is closed normally , return 0
/// Erroneous , return SOCKET_ERROR, You can use WSAGetLastError() Get a specific error code .
recv_length = recv(socket_client, buffer, BUFFER_SIZE, 0);
if (recv_length == 0)
{
std::cout << "The client is disconnected." << std::endl;
return EXIT_FAILURE;
}
else if (recv_length == SOCKET_ERROR)
{
show_error_code();
closesocket(socket_client);
return EXIT_FAILURE;
}
else if (recv_length < 0 && recv_length > BUFFER_SIZE)
{
std::cout << "recvieved length is not correct. length is " << recv_length << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int send_message(SOCKET &socket, char* buffer, int buffer_length)
{
DEBUG_FUNCTION_NAME()
/// int WSAAPI send([in] SOCKET s,[in] const char *buf, [in] int len,[in] int flags);
/// To connected SOCKET Send data on
/// Parameters
/// s Connected SOCKET The descriptor
/// buf The first address of the data to be sent
/// len Length of data to be sent
/// flags A set of specified call flags , It can be spliced by bit and
/// MSG_DONTROUTE The specified data is not subject to routing
/// MSG_OOB send out ODB data , Only for streaming services , for example SOCK_STREAM
/// Return value
/// No mistake , Returns the number of bytes sent
/// Erroneous , return SOCKET_ERROR, And through WSAGetLastError() Get a specific error code
int length = send(socket, buffer, buffer_length, 0);
if(SOCKET_ERROR == length)
{
show_error_code();
return EXIT_FAILURE;
}
std::cout << "Expected length is " << buffer_length << ", sent length is " << length << std::endl;
return EXIT_SUCCESS;
}
#endif // CPP_NETWORK_COMMUNICATION_COMMON_H
2. CMakeLists.txt
# Specify the lowest CMAKE edition
CMAKE_MINIMUM_REQUIRED(VERSION 3.17 FATAL_ERROR)
# Create project
PROJECT(cpp_network_communication)
if (CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
add_compile_definitions(DEBUG)
endif()
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
# Appoint CPLUSPLUS standard
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_C_STANDARD 11)
SET(CMAKE_C_STANDARD_REQUIRED ON)
ADD_EXECUTABLE(tcp_server tcp/tcp_server.cpp)
ADD_EXECUTABLE(tcp_client tcp/tcp_client.cpp)
ADD_EXECUTABLE(udp_server udp/udp_server.cpp)
ADD_EXECUTABLE(udp_client udp/udp_client.cpp)
ADD_EXECUTABLE(udp_server_boardcast udp/udp_server_boardcast.cpp)
ADD_EXECUTABLE(udp_client_boardcast udp/udp_client_boardcast.cpp)
ADD_EXECUTABLE(udp_server_multicast udp/udp_server_multicast.cpp)
ADD_EXECUTABLE(udp_client_multicast udp/udp_client_multicast.cpp)
ADD_EXECUTABLE(udp_server_multicast_config udp/udp_server_multicast_config.cpp)
3. TCP
3.1 The server (tcp_server.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_server;
if (create_socket(socket_server, SOCK_STREAM))
return EXIT_FAILURE;
if (bind_local(socket_server, AF_INET, htonl(INADDR_ANY), TCP_SERVER_PORT))
return EXIT_FAILURE;
if (start_listen(socket_server))
return EXIT_FAILURE;
// Single connection
SOCKET socket_client;
std::cout << "waiting for client ..." << std::endl;
if (!wait_connect(socket_server, socket_client))
{
char buffer[BUFFER_SIZE + 1]{
0};
for (size_t i = 0; i < COUNT; i++)
{
int length = 0;
std::cout << "waiting for data ..." << std::endl;
if (!recv_message(socket_client, buffer, length))
{
std::cout << "\trecv message: " << buffer << std::endl;
char *message = "server send client.";
send_message(socket_client, message, strlen(message) + 1);
}
std::cout << "\trecv message: index = " << i << std::endl;
}
closesocket(socket_client);
}
release();
system("PAUSE");
return EXIT_SUCCESS;
}
3.2 client (tcp_client.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_client;
if (create_socket(socket_client, SOCK_STREAM))
return EXIT_FAILURE;
// Generally, the client does not bind
// If no binding is specified , In the call connect Function time , The system automatically binds a local unique port to IP. here , Every time you reconnect , Port number and IP It may not be the same ( Especially in many IP On a host )
// If binding , Then the client has a fixed IP Address and port number
if (bind_local(socket_client, AF_INET, inet_addr("127.0.0.1"), TCP_Client_PORT))
return EXIT_FAILURE;
if (connect_to_server(socket_client, AF_INET, inet_addr("127.0.0.1"), TCP_SERVER_PORT))
return EXIT_FAILURE;
for (int i = 0; i < COUNT; i++)
{
char *message = "client send to server.";
send_message(socket_client, message, strlen(message) + 1);
char buffer[BUFFER_SIZE]{
0};
int recv_length;
recv_message(socket_client, buffer, recv_length);
std::cout << buffer << std::endl;
Sleep(1000);
}
closesocket(socket_client);
release();
system("PAUSE");
return EXIT_SUCCESS;
}
4. UDP unicast
4.1 The server /( For the first time ) The receiver (udp_server.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_server;
if (create_socket(socket_server, SOCK_DGRAM))
return EXIT_FAILURE;
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_server, AF_INET, htonl(INADDR_ANY), UDP_SERVER_PORT))
return EXIT_FAILURE;
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(SOCKADDR_IN));
int length = sizeof(SOCKADDR);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_server, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&client_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
char *message = "server send client.";
sendto(socket_server, message, strlen(message) + 1, 0, (SOCKADDR *)&client_addr, length);
}
closesocket(socket_server);
release();
system("PAUSE");
return 0;
}
4.2 client /( For the first time ) The sender (udp_client.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_client;
if (create_socket(socket_client, SOCK_DGRAM))
return EXIT_FAILURE;
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_client, AF_INET, inet_addr("127.0.0.1"), UDP_CLIENT_PORT))
return EXIT_FAILURE;
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(UDP_SERVER_PORT);
char *message = "client send to server.";
sendto(socket_client, message, strlen(message) + 1, 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
int length = sizeof(SOCKADDR);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_client, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&server_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &server_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
Sleep(1000);
}
closesocket(socket_client);
system("PAUSE");
WSACleanup();
return 0;
}
5. radio broadcast
5.1 The server /( For the first time ) The receiver (udp_server_boardcast.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_server;
if (create_socket(socket_server, SOCK_DGRAM))
return EXIT_FAILURE;
bool bOpt = true;
setsockopt(socket_server, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_server, AF_INET, htonl(INADDR_ANY), UDP_SERVER_PORT))
return EXIT_FAILURE;
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(SOCKADDR_IN));
int length = sizeof(SOCKADDR);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_server, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&client_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
char *message = "server send client.";
sendto(socket_server, message, strlen(message) + 1, 0, (SOCKADDR *)&client_addr, length);
}
closesocket(socket_server);
release();
system("PAUSE");
return 0;
}
5.2 client /( For the first time ) The sender (udp_client+bpardcast.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_client;
if (create_socket(socket_client, SOCK_DGRAM))
return EXIT_FAILURE;
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_client, AF_INET, inet_addr("127.0.0.1"), UDP_CLIENT_PORT))
return EXIT_FAILURE;
bool bOpt = true;
setsockopt(socket_client, SOL_SOCKET, SO_BROADCAST, (char *)&bOpt, sizeof(bOpt));
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN server_addr;
memset(&server_addr, 0, sizeof(server_addr));
// 255.255.255.255 Restricted broadcast address , Routers don't forward , Only on this machine
// All host numbers are 1, Directional address , Only the current subnet can be sent
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(UDP_SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr("255.255.255.255");
char *message = "client send to server.";
sendto(socket_client, message, strlen(message) + 1, 0, (SOCKADDR *)&server_addr, sizeof(SOCKADDR));
int length = sizeof(SOCKADDR);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_client, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&server_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &server_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
Sleep(1000);
}
closesocket(socket_client);
system("PAUSE");
WSACleanup();
return 0;
}
6. many / Multicast
6.1 The server /( For the first time ) The receiver (udp_server_multicast.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_server;
if (create_socket(socket_server, SOCK_DGRAM))
return EXIT_FAILURE;
// Set address reuse
bool is_reuse_addr = true;
if (setsockopt(socket_server, SOL_SOCKET, SO_REUSEADDR, (char *)&is_reuse_addr, sizeof(is_reuse_addr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_server, AF_INET, htonl(INADDR_ANY), UDP_SERVER_PORT))
return EXIT_FAILURE;
// Join multicast
struct ip_mreq imr;
imr.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS);
imr.imr_interface.s_addr = htonl(INADDR_ANY); // In this case , The interface address is selected by the system . In the environment of multiple network cards , Something could go wrong
// imr.imr_interface.s_addr = inet_addr(INTERFACE_ADDRESS); // Directly specify the specific network card
// Join the multicast group
if (setsockopt(socket_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr, sizeof(imr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(SOCKADDR_IN));
int length = sizeof(SOCKADDR);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_server, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&client_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
char *message = "server send to client.";
sendto(socket_server, message, strlen(message) + 1, 0, (SOCKADDR *)&client_addr, length);
}
closesocket(socket_server);
release();
system("PAUSE");
return 0;
}
6.1 client /( For the first time ) The sender (udp_client_multicast.cpp)
#include "common/common.h"
int main()
{
WSADATA wsaData;
if (init(wsaData))
return EXIT_FAILURE;
SOCKET socket_client;
if (create_socket(socket_client, SOCK_DGRAM))
return EXIT_FAILURE;
// Set address reuse
bool is_reuse_addr = true;
if (setsockopt(socket_client, SOL_SOCKET, SO_REUSEADDR, (char *)&is_reuse_addr, sizeof(is_reuse_addr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
// The party who accepts the data for the first time , Binding must be performed ; otherwise , Optional
// Do not perform binding operation , On the first call recvfrom when , The system binds a unique address and port
// After binding , Have a unique address and port
if (bind_local(socket_client, AF_INET, htonl(INADDR_ANY), UDP_CLIENT_PORT))
return EXIT_FAILURE;
// Join multicast
struct ip_mreq imr;
imr.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS);
imr.imr_interface.s_addr = htonl(INADDR_ANY); // In this case , The interface address is selected by the system . In the environment of multiple network cards , Something could go wrong
// imr.imr_interface.s_addr = inet_addr(INTERFACE_ADDRESS); // Directly specify the specific network card
if (setsockopt(socket_client, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr, sizeof(imr)))
{
show_error_code();
release();
return EXIT_FAILURE;
}
for (size_t i = 0; i < COUNT; i++)
{
SOCKADDR_IN server_addr;
ZeroMemory(&server_addr, sizeof(SOCKADDR_IN));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MULTICAST_PORT);
server_addr.sin_addr.s_addr = inet_addr(MULTICAST_ADDRESS);
int length = sizeof(SOCKADDR);
char *message = "client send to server.";
sendto(socket_client, message, strlen(message) + 1, 0, (SOCKADDR *)&server_addr, length);
Sleep(1000);
char buffer[BUFFER_SIZE + 1]{
0};
int recv_length = recvfrom(socket_client, buffer, BUFFER_SIZE, 0, (SOCKADDR *)&server_addr, &length);
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &server_addr.sin_addr.s_addr, addr, INET_ADDRSTRLEN);
std::cout << "\tThe client addr is " << addr << std::endl;
std::cout << "\tThe length of recieved data is " << recv_length << std::endl;
std::cout << "\tThe recieved data is " << buffer << std::endl;
}
closesocket(socket_client);
release();
system("PAUSE");
return 0;
}
边栏推荐
- Since I used the hiflow scene connector, I don't have to worry about becoming a "drowned chicken" anymore
- [GNN report] Li Jia, Hong Kong University of science and technology: Rethinking graph anomaly detection - what kind of graph neural network do we need?
- 【GNN报告】华为诺亚实验室周敏:曲率视角下的图数据建模与分析
- [arxiv2022] grouptransnet: Group transformer Network for RGB - D Salient Object Detection
- Cases on classes and objects
- Xmodem、Ymodem和Zmodem协议是最常用的三种通信协议
- SSH password free login configuration
- HCIP第十天(初始BGP边界网关协议)
- Intel raid模拟器下载
- 沉淀2年的 Jira 自动化经验分享
猜你喜欢

数据分析与隐私安全成 Web3.0 成败关键因素,企业如何布局?

【arXiv2022】GroupTransNet: Group Transformer Network for RGB-D Salient Object Detection

Initializing, cleaning up and const decorating member functions of constructors

DP+回溯分割回文串的系列问题

这是一个笑话

Intel raid simulator Download

MySQL和Navicat的安装与配置

牛客刷题系列之初阶版(自守数,返回小于 N 的质数个数,第一个只出现一次的字符)
[email protected], "/>Shell variables, system predefined variables $home, $pwd, $shell, $user, custom variables, special variables $n, $, $*, [email protected],

【arXiv2022】GroupTransNet: Group Transformer Network for RGB-D Salient Object Detection
随机推荐
物联网安装调试员丨让“智慧”生活早日来临
浅谈——网络安全架构设计(二)
js小游戏奔跑的熊和猫源码
"Weilai Cup" 2022 Niuke summer multi school training camp 1
二叉树表达式求值 ~
Swift - red modifier
Arcgis js api二次开发——加载国家天地图
Qgraicsview implementation palette
SOLIDWORKS CAM数据无法恢复,因为已检测到经化零件。
Android安全专题-so逆向入门和使用ida动态调试
YAML语法介绍和各种数据类型
Talking about -- network security architecture design (4)
吆喝一声就解决了
Talking about -- network security architecture design (III)
MySQL和Navicat的安装与配置
小迪和小辉
Go gin: multi file upload
30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验?
Merge output under different where conditions
坚持陪同学习