函数socket()可以创建一个socket对象:
SOCKET WSAAPI socket(
__in int af, //协议的地址家族,在Windows操作系统中,取值只能是AF_INET
//表示该套接字在Internet域中进行通信
__in int type, //套接字类型,当af=AF_INET时只有3种取值:
//SOCK_STREAM---TCP,数据被看作字节流,无长度限制
//SOCK_DGRAM---UDP,数据包以独立包形式发送
//SOCK_RAW---Raw sockets,允许对较低层协议如IP、ICMP直接访问
__in int protocol //指定网络协议:IPPROTO_IP、IPPROTO_UDP、IPPROTO_RAW
);
返回值:
成功时,返回一个创建好的套接字;
失败时,返回INVALID_SOCKET,可调用WSAGetLastError()函数查看错误信息。
socket函数使用实例如下:
#ifndef UNICODE
#define UNICODE 1
#endif
// link with Ws2_32.lib
#pragma comment(lib,"Ws2_32.lib")
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h> // Needed for _wtoi
int __cdecl wmain(int argc, wchar_t **argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData = {0};
int iResult = 0;
// int i = 1;
SOCKET sock = INVALID_SOCKET;
int iFamily = AF_UNSPEC;
int iType = 0;
int iProtocol = 0;
// Validate the parameters
if (argc != 4) {
wprintf(L"usage: %s <addressfamily> <type> <protocol>/n", argv[0]);
wprintf(L"socket opens a socket for the specified family, type, & protocol/n");
wprintf(L"%ws example usage/n", argv[0]);
wprintf(L" %ws 0 2 17/n", argv[0]);
wprintf(L" where AF_UNSPEC=0 SOCK_DGRAM=2 IPPROTO_UDP=17/n", argv[0]);
return 1;
}
iFamily = _wtoi(argv[1]);
iType = _wtoi(argv[2]);
iProtocol = _wtoi(argv[3]);
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
wprintf(L"WSAStartup failed: %d/n", iResult);
return 1;
}
wprintf(L"Calling socket with following parameters:/n");
wprintf(L" Address Family = ");
switch (iFamily) {
case AF_UNSPEC:
wprintf(L"Unspecified");
break;
case AF_INET:
wprintf(L"AF_INET (IPv4)");
break;
case AF_INET6:
wprintf(L"AF_INET6 (IPv6)");
break;
case AF_NETBIOS:
wprintf(L"AF_NETBIOS (NetBIOS)");
break;
case AF_BTH:
wprintf(L"AF_BTH (Bluetooth)");
break;
default:
wprintf(L"Other");
break;
}
wprintf(L" (%d)/n", iFamily);
wprintf(L" Socket type = ");
switch (iType) {
case 0:
wprintf(L"Unspecified");
break;
case SOCK_STREAM:
wprintf(L"SOCK_STREAM (stream)");
break;
case SOCK_DGRAM:
wprintf(L"SOCK_DGRAM (datagram)");
break;
case SOCK_RAW:
wprintf(L"SOCK_RAW (raw)");
break;
case SOCK_RDM:
wprintf(L"SOCK_RDM (reliable message datagram)");
break;
case SOCK_SEQPACKET:
wprintf(L"SOCK_SEQPACKET (pseudo-stream packet)");
break;
default:
wprintf(L"Other");
break;
}
wprintf(L" (%d)/n", iType);
wprintf(L" Protocol = %d = ", iProtocol);
switch (iProtocol) {
case 0:
wprintf(L"Unspecified");
break;
case IPPROTO_ICMP:
wprintf(L"IPPROTO_ICMP (ICMP)");
break;
case IPPROTO_IGMP:
wprintf(L"IPPROTO_IGMP (IGMP)");
break;
case IPPROTO_TCP:
wprintf(L"IPPROTO_TCP (TCP)");
break;
case IPPROTO_UDP:
wprintf(L"IPPROTO_UDP (UDP)");
break;
case IPPROTO_ICMPV6:
wprintf(L"IPPROTO_ICMPV6 (ICMP Version 6)");
break;
default:
wprintf(L"Other");
break;
}
wprintf(L" (%d)/n", iProtocol);
sock = socket(iFamily, iType, iProtocol);
if (sock == INVALID_SOCKET)
wprintf(L"socket function failed with error = %d/n", WSAGetLastError() );
else
wprintf(L"socket function succeeded/n", WSAGetLastError() );
WSACleanup();
return 0;
}
函数bind用来将本地地址附加到所创建的套接字上以便能够有效地标识套接字:
int bind(
__in SOCKET s, //标识未绑定套接字的句柄
__in const struct sockaddr *name, //用来赋予套接字地址,一般用struct sockaddr_in结构表示
__in int namelen //name指向的值的字节大小
);
返回值:
成功时,返回0;
失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。
其中:
struct sockaddr {
ushort sa_family; //地址家族,一般为AF_INET
char sa_data[14]; //14字节的IP地址
};
struct sockaddr_in {
short sin_family; //Windows下为AF_INET,表示该socket位于Internet域
u_short sin_port; //指定服务端口
struct in_addr sin_addr; //用于保存IP地址
char sin_zero[8]; //只起填充作用
};
bind函数使用实例如下:
#include <stdio.h>
#include "winsock2.h"
#include <windows.h>
#pragma comment(lib, "wininet.lib")
void main() {
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()/n");
//----------------------
// Create a SOCKET for listening for
// incoming connection requests
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld/n", WSAGetLastError());
WSACleanup();
return;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);
//----------------------
// Bind the socket.
if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed./n");
closesocket(ListenSocket);
return;
}
WSACleanup();
return;
}
shutdown函数用来中断socket连接,通知接收端或发送端“停止接收数据”或“停止发送数据”:
int shutdown(
__in SOCKET s, //指定要中断的套接字连接
__in int how //指定关闭的方式:SD_RECEIVE(禁止接收)、SD_SEND(禁止发送)、
//SD_BOTH(同时禁止接收和发送)
);
返回值:
成功时,返回0;
失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。
closesocket函数用来关闭套接字:
int closesocket(
__in SOCKET s //指定要关闭的套接字
);
返回值:
成功时,返回0;
失败时,返回SOCKET_ERROR,调用WSAGetLastError函数查看进一步错误信息。