289 lines
8.1 KiB
C++
289 lines
8.1 KiB
C++
/******************************************************************************\
|
|
* connectbyname.cpp
|
|
*
|
|
* This IPv6 sample demonstrates the use of WSAConnectByName.
|
|
*
|
|
* WSAConnectByName is new to Windows Sockets in Windows Vista.
|
|
*
|
|
* This sample requires that TCP/IP version 6 be installed on the system (default
|
|
* configuration for Windows Vista).
|
|
*
|
|
* IPv6 socket calls WSAConnectByName to resolve name and connect to listener in
|
|
* a single API call. The local and remote addresses are also returned. The connecting
|
|
* entity sends some data after WSAConnectByName. The accepting entity receives the
|
|
* peer data. Then both sides close the connection.
|
|
*
|
|
*
|
|
* This is a part of the Microsoft Source Code Samples.
|
|
* Copyright 1996 - 2006 Microsoft Corporation.
|
|
* All rights reserved.
|
|
* This source code is only intended as a supplement to
|
|
* Microsoft Development Tools and/or WinHelp documentation.
|
|
* See these sources for detailed information regarding the
|
|
* Microsoft samples programs.
|
|
\******************************************************************************/
|
|
|
|
#ifdef _IA64_
|
|
#pragma warning (disable: 4311)
|
|
#pragma warning (disable: 4312)
|
|
#endif
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <mstcpip.h>
|
|
#include <stdio.h>
|
|
#include <strsafe.h>
|
|
|
|
|
|
// "Safe" macros
|
|
|
|
#define CLOSESOCK(s) \
|
|
if(INVALID_SOCKET != s) {closesocket(s); s = INVALID_SOCKET;}
|
|
|
|
#define ERR(e) \
|
|
{ \
|
|
printf("%s:%s failed: %d [%s@%ld]\n",__FUNCTION__,e,WSAGetLastError(),__FILE__,__LINE__); \
|
|
}
|
|
|
|
|
|
// Constants
|
|
|
|
#define WS_VER 0x0202
|
|
|
|
#define CONNECT_TIMEOUT_VAL 30000
|
|
|
|
#define TST_MSG "Hello\0"
|
|
|
|
// Helper functions
|
|
|
|
VOID SET_PORT(PSOCKADDR pAddr,USHORT port)
|
|
{
|
|
if (AF_INET6 == pAddr->sa_family)
|
|
{
|
|
((SOCKADDR_IN6*)pAddr)->sin6_port = htons(port);
|
|
}
|
|
else
|
|
{
|
|
((SOCKADDR_IN*)pAddr)->sin_port = htons(port);
|
|
}
|
|
}
|
|
|
|
|
|
typedef BOOL (WSAAPI * LPFN_WSACONNECTBYNAME) (SOCKET s,
|
|
LPCSTR name,
|
|
LPCSTR port,
|
|
LPDWORD LocalAddressLength,
|
|
LPSOCKADDR LocalAddress,
|
|
LPDWORD RemoteAddressLength,
|
|
LPSOCKADDR RemoteAddress,
|
|
TIMEVAL* timeout,
|
|
LPOVERLAPPED reserved);
|
|
|
|
LPFN_WSACONNECTBYNAME GetWSAConnectByNameFunctionPointer()
|
|
{
|
|
LPFN_WSACONNECTBYNAME WSAConnectByName = NULL;
|
|
HMODULE hWs2_32 = LoadLibraryA("ws2_32");
|
|
|
|
WSAConnectByName = (LPFN_WSACONNECTBYNAME)GetProcAddress(hWs2_32,"WSAConnectByNameA");
|
|
|
|
FreeLibrary(hWs2_32);
|
|
|
|
return WSAConnectByName;
|
|
}
|
|
|
|
VOID PrintSockaddr(PSOCKADDR pSockaddr,DWORD dwSize)
|
|
{
|
|
CHAR szString[MAX_PATH] = {0};
|
|
DWORD dwStringSize = sizeof szString;
|
|
|
|
if (SOCKET_ERROR == WSAAddressToStringA(pSockaddr,dwSize,NULL,szString,&dwStringSize))
|
|
{
|
|
ERR("WSAAddressToString");
|
|
return;
|
|
}
|
|
|
|
printf("%s\n",szString);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
int __cdecl main()
|
|
{
|
|
WSADATA wsd;
|
|
INT nStartup = 0,
|
|
err = 0,
|
|
nAddrSize = 0,
|
|
rc = 0;
|
|
SOCKET lsock = INVALID_SOCKET,
|
|
csock = INVALID_SOCKET,
|
|
asock = INVALID_SOCKET;
|
|
SOCKADDR_STORAGE listenAddr = {0},
|
|
localAddr = {0},
|
|
remoteAddr = {0};
|
|
USHORT uport = 0;
|
|
CHAR szPort[MAX_PATH] = {0},
|
|
hostname[MAX_PATH] = {0},
|
|
buf[MAX_PATH] = {0};
|
|
DWORD dwLocalAddrLen = sizeof localAddr,
|
|
dwRemoteAddrLen = sizeof remoteAddr;
|
|
TIMEVAL timeval = {CONNECT_TIMEOUT_VAL,0};
|
|
LPFN_WSACONNECTBYNAME WSAConnectByName = GetWSAConnectByNameFunctionPointer();
|
|
|
|
__try
|
|
{
|
|
err = WSAStartup(WS_VER,&wsd);
|
|
if (err)
|
|
{
|
|
WSASetLastError(err);
|
|
ERR("WSAStartup");
|
|
__leave;
|
|
}
|
|
else
|
|
nStartup++;
|
|
|
|
//Setup listener
|
|
if (INVALID_SOCKET == (lsock = socket(AF_INET6,
|
|
SOCK_STREAM,
|
|
0
|
|
)))
|
|
{
|
|
ERR("socket");
|
|
__leave;
|
|
}
|
|
|
|
listenAddr.ss_family = (ADDRESS_FAMILY)AF_INET6;
|
|
|
|
INETADDR_SETANY((SOCKADDR*)&listenAddr);
|
|
|
|
if (SOCKET_ERROR == bind(lsock,
|
|
(SOCKADDR*)&listenAddr,
|
|
sizeof listenAddr
|
|
))
|
|
{
|
|
ERR("bind");
|
|
__leave;
|
|
}
|
|
|
|
nAddrSize = sizeof listenAddr;
|
|
|
|
if (SOCKET_ERROR == getsockname(lsock,
|
|
(SOCKADDR*)&listenAddr,
|
|
&nAddrSize
|
|
))
|
|
{
|
|
ERR("getsockname");
|
|
__leave;
|
|
}
|
|
|
|
//get listening port
|
|
uport = htons((USHORT)INETADDR_PORT((SOCKADDR*)&listenAddr));
|
|
|
|
//convert uport to string for WSAConnectByName
|
|
StringCbPrintfA(szPort,sizeof szPort,"%u",uport);
|
|
|
|
printf("Listening on port %s\n",szPort);
|
|
|
|
|
|
if (SOCKET_ERROR == listen(lsock,
|
|
1
|
|
))
|
|
{
|
|
ERR("listen");
|
|
__leave;
|
|
}
|
|
|
|
//client WSAConnectByName
|
|
|
|
if (INVALID_SOCKET == (csock = socket(AF_INET6,
|
|
SOCK_STREAM,
|
|
0
|
|
)))
|
|
{
|
|
ERR("socket");
|
|
__leave;
|
|
}
|
|
|
|
if(SOCKET_ERROR == gethostname(hostname,sizeof hostname))
|
|
{
|
|
ERR("gethostname");
|
|
__leave;
|
|
}
|
|
|
|
if (!WSAConnectByName(csock,
|
|
hostname,
|
|
szPort,
|
|
&dwLocalAddrLen,
|
|
(SOCKADDR*)&localAddr,
|
|
&dwRemoteAddrLen,
|
|
(SOCKADDR*)&remoteAddr,
|
|
&timeval,
|
|
NULL
|
|
))
|
|
{
|
|
ERR("WSAConnectByName");
|
|
__leave;
|
|
}
|
|
|
|
//send some data
|
|
|
|
if (SOCKET_ERROR == (rc = send(csock,
|
|
TST_MSG,
|
|
lstrlenA(TST_MSG),
|
|
0
|
|
)))
|
|
{
|
|
ERR("send");
|
|
__leave;
|
|
}
|
|
|
|
printf("Sent %d bytes to listener after WSAConnectByName.\n",rc);
|
|
|
|
printf("Addresses returned after WSAConnectByName:\n");
|
|
printf("Local address: ");
|
|
PrintSockaddr((SOCKADDR*)&localAddr,sizeof localAddr);
|
|
printf("Remote address: ");
|
|
PrintSockaddr((SOCKADDR*)&remoteAddr,sizeof remoteAddr);
|
|
printf("\n");
|
|
|
|
//accept connection
|
|
if (INVALID_SOCKET == (asock = accept(lsock,
|
|
NULL,
|
|
NULL
|
|
)))
|
|
{
|
|
ERR("accept");
|
|
__leave;
|
|
}
|
|
|
|
//recv client data
|
|
if (SOCKET_ERROR == (rc = recv(asock,
|
|
buf,
|
|
sizeof buf,
|
|
0
|
|
)))
|
|
{
|
|
ERR("recv");
|
|
__leave;
|
|
}
|
|
|
|
printf("Received %d bytes after accept.\n",rc);
|
|
|
|
}
|
|
__finally
|
|
{
|
|
CLOSESOCK(lsock);
|
|
CLOSESOCK(csock);
|
|
CLOSESOCK(asock);
|
|
if(nStartup) WSACleanup();
|
|
}
|
|
|
|
return 0;
|
|
}
|