1、套接字概述
套接字是网络通信的基石,是网络通信的基本构件。
所谓套接字,实际上是一个指向传输提供者的句柄。在WinSock中,就是通过操作该句柄来实现网络通信和管理的。根据性质和作用不同,套接字可以分为原始套接字、流式套接字、数据包套接字3种。
(1)原始套接字:原始套接字是在WinSock2规范中提出的,他能够使程序开发人员对底层的网络传输机制进行控制,在原始套接字下接受的数据中包含IP头
(2)流式套接字:流式套接字提供双向、有序、可靠的数据传输服务,该类型套接字在通信前需要双方建立连接。TCP协议采用的就是流式套接字。
(3)数据包套接字:数据报套接字提供双向的数据流,但是它不能保证数据传输的可靠性、有序性、和无重复性。UDP协议采用就是数据包套接字。
2、TCP套接字的socket编程
TCP是面向连接的、可靠的传输协议。通信双方建立连接就可以利用TCP进行通信。TCP提供了数据确认和数据重传的机制,保证了发送的数据一定能到达通信的对方。
基于TCP面向连接的socket编程的
服务器端程序流程如下:
(1)创建套接字socket。
(2)将创建的套接字绑定(bind)到本地的地址和端口上
(3)设置套接字的状态为监听状态(listen),准备接受客户端的连接请求。
(4)接受请求(accpet),同时返回得到一个用于连接的新套接字。
(5)使用这个新套接字进行通信(通信函数使用send/recv)。
(6)通信完毕,释放套接字资源(closesocket)。
基于TCP面向连接的socket编程的
客户端程序流程如下:
(1)创建套接字socket。
(2)向服务器发送连接请求(connect)
(3)请求连接后与服务器进行通信操作(send/recv)
(4)释放套接字资源(closesocket)
3、UDP的套接字的socket编程
UDP是无连接的、不可靠的传输协议。采用UDP进行通信时,不需要建立连接,可以直接向一个IP地址发送数据,但是不能保证对方能收到。可以把服务器称为接收端,客服端就是发送数据的发送端。
基于UDP面向无连接的socket编程的发送端程序流程如下:
(1)创建套接字socket
(2)将套接字绑定(bind)带一个本地地址和端口上
(3)等待接收数据(recvfrom)
(4)释放套接字资源(closesocket)
基于UDP面向无连接的socket编程的接收端程序流程如下:
(1)创建套接字socket
(2)向服务器发送数据(sendto)
(3)释放套接字资源(closesocket)
4、套接字函数介绍
(1)WSAStartup函数:初始化套接字库。其原型如下:
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
注意:WSAStartup函数用于初始化Ws2_32.dll动态链接库。在使用套接字函数之前,一定要初始化Ws2_32.dll动态链接库。
说明:1)wVersionRequested:表示调用者使用的Windows socket的版本,该字节记录修订版本,低字节记录主版本。例如版本2.1,则高字节记录1,低字节记录2
2)lpWSAData:是一个WSADATA结构指针,该结构详细记录了Windows套接字的相关信息。其定义如下:
typedef struct WSAData
{
WORD wVersion;
WORD wHighVersion;
char szDwscription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STAUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR* lpVendorlnfo;
}WSADATA,FAR*LPWSADATA;
(2)socket函数:创建一个套接字
SOCKET socket(int af,int type,int protocol);
说明:1)af:表示一个地址家族,通常为AF_INET
2)type:表示套接字类型,如果未SOCK_STREAM,表示创建面向连接的流式套接字;为SOCK_DGRAM,表示创建面向无连接的数据报套接字;SOCK_RAW,表示创建原始套接字。对于这些值,用户可以在Winsock2.h头文件中找到
3)potocol:表示套接口所用的协议,若果用户不指定,可以设置为0
4)返回值:创建的套接字句柄
(3)bind函数:将套接字绑定到指定的端口和地址上。
int bind(SOCKET s,const stuct sockaddr FAR* name,int namelen);
说明:
1)s:表示套接字标识
2)name:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号
3)namelen:确定name缓冲区的长度
4)返回值:如果函数执行成功,则返回值为0,否则为SOCKET_ERROR
(4)listen函数:将嵌套字设定为监听模式。对于流式套接字,必须处于监听模式才能够接收客户端套接字的连接。
int listen(SOCKET S,int backlog);
说明:
1)s:表示套接字标识
2)backlog:表示等待连接的最大队列长度。
(5)accept函数:接受客户端的连接。在流式套接字中,只有在套接字处于监听状态,才能接受客户端的连接。
SOCKET accept(SOCKET s,struct sockaddr FAR* addr,int FAR* addrlen);
说明:
1)s:表示套接字标识
2)addr:是一个sockddr_in结构指针,包含一组客户端的端口号、IP地址等信息。
3)addrlen:用于接收参数addr的长度
(6)closesocket函数:关闭套接字
int closesocket(SOCKET s);
(7)connect函数:发送连接请求
int connect(SOCKET s,const struct sockaddr FAR* name,int namelen);
说明:
1)s:表示套接字标识
2)name:表示套接字s要连接的主机地址和端口号
3)namelen:是neme缓冲区的长度
4)返回值:执行成功,返回值为0,否则放回SOCKET_ERROR.用户可以通过WSAGETLASTERROR得到其错误描述
(8)htons函数:将一个16位的无符号短整型数据由主机排列方式转换为网络排列方式
u_short htons(u_short hostshort);
说明:
1)hostshort:是一个主机排列方式的无符号短整型数据
2)返回值:函数返回值是16位的网络排列方式数据
(9)htonl函数:将一个无符号长整型数据由主机排列方式转换为网络排列方式
u_long htonl(u_long hostlong);
说明:
1)hostlong:表示一个主机排列方式的无符号长整型数据
2)返回值:32位的网络排列方式数据
(10)inet_addr函数:将一个由字符串表示的地址转换为32位的无符号长整型数据
unsigned long inet_addr(const char FAR* cp);
说明:
1)cp:表示一个IP复制的字符串
2)返回值:32位无符号整数
(11)recv函数:从面向连接的套接字中接收数据
int recv(SOCKET s,char FAR* BUF,int len,int,flags);
说明:
1)s:表示套接字标识
2)buf:接收数据的缓冲区
3)len:buf的长度
4)flags:函数的调用方式。如果未MSG_PEEK,则表示查看传来的数据,在序列前端的数据会被复制一份到缓冲区中,但是这个数据不会从序列中移走;如果是MSG_OOB,则表示用来处理Out-Of-Band数据,也就是外带数据。
(12)send函数:在面向连接方式的套接字间发送数据。
int send(SOCKET s,const char FAR* buf,int len,int flags);
说明:
1)s:表示套接字标识
2)buf:表示存放要发送数据的缓冲区
3)len:缓冲区长度
4)flags:函数的调用方式
(13)recvfrom函数:接收一个数据报信息并保存源地址
int recvfrom(SOCKET s,char FAR* buf,int len,int flags, struct sockaddr FAR* from,int FAR* fromlen);
说明:
1)s:表示套接字标识
2)buf:指向缓冲区的指针,用来接收数据
3)len:缓冲区的长度
4)flags:通过设置这个值可以影响函数调用的行为
5)from:是一个指向地址结构的指针,用来接收发送数据防的地址信息
6)fromlen:表示缓冲区的长度
(14)sendto函数:向一个特定的目的方发送数据
int sendto(SOCKET s,const char FAR* buf,int len,int flags,const struct sockaddr FAR* to,int tolen);
说明:
1)s:表示一个(可能已经建立连接的)套接字标识
2)buf:指向缓冲区的指针,该缓冲区包含将要发送的数据
3)len:表示缓冲区的长度
4)flags:通过设置这个值可以影响函数的调用行为
5)to:指定目标调节子的地址
6)tolen:表示缓冲区的长度
(15)WSACleanup函数:释放为Ws2_32.dll动态链接库初始化时分配的资源
int WSACleanup(void);
使用该函数关闭动态链接库:
WSACleanup();