Winsock

历史

MS-DOS与早期版本的Microsoft Windows使用的网络协议是NetBIOS. 因此，各方提供了各自的MS-DOS上的TCP/IP实现。由于各种解决方案的API函数名并不统一，使得软件开发者难以下决心转到TCP/IP协议上。
1991年10月，以Martin Hall, Mark Towfiq, Geoff Arnold, Henry Sanders为首在CompuServe BBS上讨论形成了Windows Sockets API规范(specification)并且版权属于这五人。

其他实现

遵从Winsock规范的TCP/IP与UDP/IP协议栈有：3Com, Beame & Whiteside, DEC, Distinct, FTP Software, Frontier, IBM, Microdyne, NetManage, Novell, Sun Microsystems, Trumpet Software International.

列出所有服务提供者

/*** Winsock 2 API Protocol Enumerator -*/#ifndef WIN32_LEAN_AND_MEAN#define WIN32_LEAN_AND_MEAN#endif#define WINSOCK_API_LINKAGE#include <winsock2.h>#include <ws2spi.h>#include <wtypes.h>#include <assert.h>#include <winnt.h>#include <stdlib.h>#include <stdio.h>#pragma comment(lib,"Ws2_32.lib")char *ExpandServiceFlags(DWORD serviceFlags){
/* A little utility function to make sense of all those bit flags */
/* The following code leaks. Yeah, I know.. Go find Buffer 0v3rfl0w$ :-) */
char *serviceFlagsText = (char *)malloc(2048);
memset(serviceFlagsText, '\0', 2048);
char *strip_comma;
/* Hey - it's only for printing and demo purposes.. */
if (serviceFlags & XP1_CONNECTIONLESS)
{
strcat(serviceFlagsText, "Connectionless, ");
}
if (serviceFlags & XP1_GUARANTEED_ORDER)
{
strcat(serviceFlagsText, "Guaranteed Order, ");
}
if (serviceFlags & XP1_GUARANTEED_DELIVERY)
{
strcat(serviceFlagsText, "Message Oriented, ");
}
if (serviceFlags & XP1_CONNECT_DATA)
{
strcat(serviceFlagsText, "Connect Data, ");
}
if (serviceFlags & XP1_DISCONNECT_DATA)
{
strcat(serviceFlagsText, "Disconnect Data, ");
}
if (serviceFlags & XP1_SUPPORT_BROADCAST)
{
strcat(serviceFlagsText, "Broadcast Supported, ");
}
if (serviceFlags & XP1_EXPEDITED_DATA)
{
strcat(serviceFlagsText, "Urgent Data, ");
}
if (serviceFlags & XP1_QOS_SUPPORTED)
{
strcat(serviceFlagsText, "QoS supported, ");
}
/** While we're quick and dirty, let's get as dirty as possible..*/
strip_comma = strrchr(serviceFlagsText, ',');
if (strip_comma)
*strip_comma = '\0';
return (serviceFlagsText);}void PrintProtocolInfo(LPWSAPROTOCOL_INFOW prot){
wprintf(L"Protocol Name: %s\n", prot->szProtocol); /* #%^@$! UNICODE...*/
printf("\tServiceFlags1:  %d (%s)\n",
prot->dwServiceFlags1,
ExpandServiceFlags(prot->dwServiceFlags1));
printf("\tProvider Flags: %d\n", prot->dwProviderFlags);
printf("\tNetwork Byte Order: %s\n",
(prot->iNetworkByteOrder == BIGENDIAN) ? "Big Endian" : "Little Endian");
printf("\tVersion: %d\n", prot->iVersion);
printf("\tAddress Family: %d\n", prot->iAddressFamily);
printf("\tSocket Type: ");
switch (prot->iSocketType)
{
case SOCK_STREAM:
printf("STREAM\n");
break;
case SOCK_DGRAM:
printf("DGRAM\n");
break;
case SOCK_RAW:
printf("RAW\n");
break;
default:
printf(" Some other type\n");
}
printf("\tProtocol: ");
switch (prot->iProtocol)
{
case IPPROTO_TCP:
printf("TCP/IP\n");
break;
case IPPROTO_UDP:
printf("UDP/IP\n");
break;
default:
printf("some other protocol\n");
}}int _cdecl main(int argc, char** argv){
LPWSAPROTOCOL_INFOW  bufProtocolInfo = NULL;
DWORD                dwSize = 0;
INT                  dwError;
INT                  iNumProt;
/** Enum Protocols - First, obtain size required*/
printf("Sample program to enumerate Protocols\n");
WSCEnumProtocols(NULL,                     // lpiProtocols
bufProtocolInfo,          // lpProtocolBuffer
&dwSize,                 // lpdwBufferLength
&dwError);               // lpErrno
bufProtocolInfo = (LPWSAPROTOCOL_INFOW)malloc(dwSize);
if (!bufProtocolInfo) {
fprintf(stderr, "SHOOT! Can't MALLOC!!\n");
exit(1);
}
/* Now, Enum */
iNumProt = WSCEnumProtocols(
NULL,                    // lpiProtocols
bufProtocolInfo,         // lpProtocolBuffer
&dwSize,                 // lpdwBufferLength
&dwError);
if (SOCKET_ERROR == iNumProt)
{
fprintf(stderr, "Darn! Can't Enum!!\n");
exit(1);
}
printf("%d Protocols detected:\n", iNumProt);
for (int i = 0;
i < iNumProt;
i++)
{
PrintProtocolInfo(&bufProtocolInfo[i]);
printf("-------\n");
}
printf("Done");
return(0);}

阻塞式程序

int nPort =65000;//指定通信端口
    WSADATA wsaData;
    WSAStartup( MAKEWORD( 2, 2 ), &wsaData );

     // 创建监听套接字，绑定本地端口，开始监听
    SOCKET sListen = socket( AF_INET,SOCK_STREAM, 0 );
    SOCKADDR_IN addr; 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons( nPort ); 
    addr.sin_addr.S_un.S_addr = INADDR_ANY; 
    bind( sListen, (sockaddr *)&addr, sizeof( addr ) ); 
    listen( sListen, 5 );

    SOCKADDR_IN saRemote; 
    int nRemoteLen = sizeof( saRemote ); 
    SOCKET sRemote = accept( sListen, (sockaddr *)&saRemote, &nRemoteLen );