Windows Socket 2
A socket handle can optionally be a file handle in Windows Sockets 2.
A socket handle from a Winsock provider can be used with other non-Winsock functions such as ReadFile, WriteFile, ReadFileEx, and WriteFileEx.
library: ws2_32.lib(set in Project->Linker->Input->Additional Dependencies)
header: winsock2.h(contains winsock functions, structures and definitions)
ws2tcpip.h contains new functions and structures used to retrieve ip address.
Iphlpapi.h header file is required if an application is using the IP Helper APIs.
Note: #include line for Iphlpapi.h should after the #include line for winsock2.h. windows.h is internally included in winsock2.h. So it is not necessary to include windows.h
For historical reasons, the Windows.h header defaults to including the Winsock.h header file for Windows Sockets 1.1.
So if you include windows.h file will confilt with the socket 2 defined in winsock2.h. In order to prevent this confliction, using WIN32_LEAN_AND_MEAN macro to stop windows.h define windows socket 1.1.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <iostream>
using namespace std;
int main() {
WSADATA wsaData;
int iRet = 0;
iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iRet != 0)
{
cout<<::GetLastError()<<endl;
return 1;
}
cout<<std::hex<<wsaData.wVersion<<endl; // 202
cout<<std::hex<<wsaData.wHighVersion<<endl; // 202
cout<<std::dec<<wsaData.szDescription<<endl; // WinSock 2.0
cout<<wsaData.szSystemStatus<<endl; // Running
cout<<wsaData.iMaxSockets<<endl; // 0
return 0;
}
Both gai_strerror and WSAGetLastError can return the error code for the last operation for invoking the api in windows socket program, the later is thread-safe.
GetAddInfo is a macro for GetAddrInfoW or getaddrinfo by whether UNICODE or _UNICODE is defined. The parameter type for this macro should use TCHAR and ADDRINFOT.
GetAddrInfoW uses wchar_t and addrinfoW as its parameter; getaddrinfo uses char and addrinfo.
Syntax for getaddrinfo:
int WSAAPI getaddrinfo(
__in const char* nodename,
__in const char* servname,
__in const struct addrinfo* hints,
__out struct addrinfo** res
);
typedef struct addrinfo
{
int ai_flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
int ai_family; // AF_INET(IPV4), AF_INET6(IPV6), AF_NETBIOS(NETBIOS), AF_BTM(BLUE TOOTH)…
int ai_socktype; // SOCK_STREAM(TCP), SOCK_DGRAM(UDP), SOCK_RAW(RAW)…
int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
size_t ai_addrlen; // Length of ai_addr
char * ai_canonname; // Canonical name for nodename
__field_bcount(ai_addrlen) struct sockaddr * ai_addr; // Binary address
struct addrinfo * ai_next; // Next structure in linked list
}
ADDRINFOA, *PADDRINFOA;
void freeaddrinfo(Note:This continues to free it until ai_next is null.
__in struct addrinfo* ai
);
struct sockaddr {
ushort sa_family;
char sa_data[14];
};
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr_in6 {sin6_family in sockaddr_in6 and sockaddr_in6_old must be AF_INET6.
short sin6_family;
u_short sin6_port;
u_long sin6_flowinfo;
struct in6_addr sin6_addr;
u_long sin6_scope_id;
};
typedef struct sockaddr_in6 SOCKADDR_IN6;
typedef struct sockaddr_in6 *PSOCKADDR_IN6;
typedef struct sockaddr_in6 FAR *LPSOCKADDR_IN6;
struct sockaddr_in6_old {
short sin6_family;
u_short sin6_port;
u_long sin6_flowinfo;
struct in6_addr sin6_addr;
};
typedef struct sockaddr_storage {
ADDRESS_FAMILY ss_family;
CHAR __ss_pad1[_SS_PAD1SIZE];
__int64 __ss_align;
CHAR __ss_pad2[_SS_PAD2SIZE];
} SOCKADDR_STORAGE, *PSOCKADDR_STORAGE;
typedef UINT_PTR SOCKET;
SOCKET socket = INVALID_SOCKET;
SOCKET WSAAPI socket(
_In_ int af,
_In_ int type,
_In_ int protocol
);
_srvsck = socket(ret->ai_family, ret->ai_socktype, ret->ai_protocol);
_srvsck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int bind(
_In_ SOCKET s,
_In_ const struct sockaddr *name,
_In_ int namelen
);
iRet = bind( _srvsck, ret->ai_addr, (int)ret->ai_addrlen);
sockaddr_in undef;
ZeroMemory(&undef, sizeof(sockaddr_in));
undef.sin_family = AF_INET;
undef.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
undef.sin_port = ::htons(11221);
iRet = bind(_srvsck, (sockaddr*)&undef, sizeof(sockaddr_in));
undef.sin_addr.S_un.S_addr = INADDR_ANY;
iRet = bind(_srvsck, (sockaddr*)&undef, sizeof(sockaddr_in));
sockaddr_in _info;
ZeroMemory(&_info, sizeof(sockaddr_in));
int _len = sizeof(sockaddr_in);
iRet = ::getsockname(_srvsck, (sockaddr*)&_info, &_len);
if (iRet == SOCKET_ERROR)
{
iRet = WSAGetLastError();
wcout<<"Failed to getsockname:. (ErrCode: "<<iRet<<")."<<endl;
}
else
{
cout<<"length of sock address:"<<_len<<endl;
char * _paddr = ::inet_ntoa(_info.sin_addr);
if (_paddr != nullptr)
cout<<_paddr<<endl;
else
cout<<"empty ip address"<<endl;
int _port = _info.sin_port;
_port = ::htons(_info.sin_port);
cout<<"port:"<<_port<<endl;
}
int listen(If set backlog to SOMAXCONN, the underlying service provider responsible for socket s will set the backlog to a maximum reasonable value. If a connection request arrives and the queue is full, the client will receive an error with an indication of WSAECONNREFUSED. If the listen function is called on an already listening socket, it will return success without changing the value for the backlog parameter.
_In_ SOCKET s,
_In_ int backlog
);
SOCKET cltSck = INVALID_SOCKET;
SOCKADDR_IN cltAddr;
int cltAddrLen = sizeof(SOCKADDR_IN);
cltSck = accept(_srvsck, (SOCKADDR*)&cltAddr, &cltAddrLen);
if (cltSck == INVALID_SOCKET)
{
iRet = ::WSAGetLastError();
wcout<<"Failed to accept: "<<gai_strerror(iRet)<<" (ErrCode: "<<iRet<<")."<<endl;
break;
}
ADDRINFOT *res = nullptr, hints;
ZeroMemory(&hints, sizeof(ADDRINFOT));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iRet = GetAddrInfo(_straddr.c_str(), _strport.c_str(), &hints, &res);
_cltSck = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
iRet = connect(_cltSck, res->ai_addr, res->ai_addrlen);
iRet = recvfrom(cltSck, (char*)msg, sizeof(TCHAR)*MAX_PATH, 0, (PSOCKADDR)&senderSck, &senderSckSize);If no error occurs, recvfrom returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned.
APPENDIX
Winsock Kernel Socket Categories
|
|
|
|
|
|
|
|
AF_INET and AF_INET6
AF_INET | AF_INET6 | |
Socket Address Structure | SOCKADDR_IN | SOCKADDR_IN6 |
Socket Type | SOCK_STREAM SOCK_DGRAM SOCK_RAW |
SOCK_STREAM SOCK_DGRAM SOCK_RAW |
Combinations |
Basic Sockets
SOCK_DGRAM + IPPROTO_UDP SOCK_RAW + IPPROTO_ XXX SOCK_RAW + IPPROTO_ XXX |
Same as AF_INET |
System supported socket catalog
On Windows XP and later, the following command can be used to list the Windows Sockets catalog to determine the service providers installed and the address family, socket type, and protocols that are supported.
netsh winsock show catalog