Windows Sockets编程学习总结

1、Windows Sockets已经封装好了具体的实现方法,在这里不深究它的机制,只是能理解和熟练使用就可以。

2、TCP、UDP
SOCK_STREAM即TCP协议,要建立连接,传送的数据,无差错,不丢失,不重复,且按序到达
SOCK_DGRAMUDP协议,不建立连接,会丢包,实时传输。
3、网络协议:
PF_INET, AF_INET: Ipv4    
PF_INET6, AF_INET6: Ipv6

AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B
127.0.0.1,它是一个特殊IP地址,表示本机地址

AF 表示ADDRESS FAMILY 地址族
PF 表示PROTOCL FAMILY 协议族

Winsock2.h中
#define AF_INET 0
#define PF_INET AF_INET
socket传递数据前需要数据封装,里面需要AF_INET的支持。

4、实现流程:

服务器:

           建立WSADATA(保存接收的数据)  ->  调用WSAStartup函数  ->  创建socket   ->   填写IP地址和端口    ->    bind()绑定IP地址和端口(判断绑定成功)   ->    监听scoket    ->   发送和接收数据   ->   断开连接   ->    关闭

使用DLL之前必须把DLL加载到当前程序,你可以在编译时加载,也可以在程序运行时加载

方法1:

#pragma comment (lib, "ws2_32.lib")

方法2:

WORD wVersionRequested;
wVersionRequested = MAKEWORD( 2, 2 );   // 请求2.2版本的WinSock库

WSAStartup是任何使用Winsock的应用程序或者DLL首先必须调用Winsock库函数.一方面它初始化 ws2_32.dll,另一方面他用于在应该程序DLL与系统Winsock库版本协商.

4.1、socket()函数 建立socket

int socket(int af, int type, int protocol);

af:协议域或协议簇。常用AF_INETAF_INET6,决定socket的地址类型。

type:指socket类型,SOCK_STREAMSOCK_DGRAM,即TCP、UDP。

protocol:指定协议,常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议,但是大部分设为0即可,会自动匹配。

return:返回一个文件的描述符,为int型,成功返回生成的SOCKET,失败返回INVALID_SOCKET

4.2、 bind() 绑定socket

 
int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); 

sock:是socket的文件描述符,addr是sockaddr结构体变量的指针,addlen是addr变量的大小,可由sizeof()计算

4.3、 connect()  连接socket

int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen);

 参数跟bind()一致

4.4、listen() 监听socket

int listen(SOCKET sock, int backlog); 

sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度

缓冲区的长度(能存放多少个客户端请求)可以通过 listen() 函数的 backlog 参数指定,但究竟为多少并没有什么标准,可以根据你的需求来定,并发量小的话可以是10或者20。
如果将 backlog 的值设置为 SOMAXCONN,就由系统来决定请求队列长度,这个值一般比较大,可能是几百,或者更多。
当请求队列满时,就不再接收新的请求,对于 Linux,客户端会收到 ECONNREFUSED 错误,对于 Windows,客户端会收到 WSAECONNREFUSED 错误。

注意:listen() 只是让套接字处于监听状态,并没有接收请求。接收请求需要使用 accept() 函数。

4.4、 accept() 接收socket

SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen);

它的参数与 listen() 和 connect() 是相同的:sock 为服务器端套接字,addr 为 sockaddr_in 结构体变量,addrlen 为参数 addr 的长度,可由 sizeof() 求得。

accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字,大家注意区分。后面和客户端通信时,要使用这个新生成的套接字,而不是原来服务器端的套接字。
最后需要说明的是:listen() 只是让套接字进入监听状态,并没有真正接收客户端请求,listen() 后面的代码会继续执行,直到遇到 accept()。accept() 会阻塞程序执行(后面代码不能被执行),直到有新的请求到来。

4.5、send()和recv()

从服务器端发送数据使用 send() 函数,它的原型为:

int send(SOCKET sock, const char *buf, int len, int flags);
sock 为要发送数据的套接字,buf 为要发送的数据的缓冲区地址,len 为要发送的数据的字节数,flags 为发送数据时的选项。

返回值和前三个参数不再赘述,最后的 flags 参数一般设置为 0 或 NULL,初学者不必深究。

在客户端接收数据使用 recv() 函数,它的原型为:

int recv(SOCKET sock, char *buf, int len, int flags);

4.6、返回值

socket()  accept()

如果成功就返回生成的SOCKET,如果失败就返回INVALID_SOCKET.

#define INVALID_SOCKET  (SOCKET)(~0)
实际上是 0xFFFFFFFF 4bytes

bind() listen() connect()

如果成功就返回0,如果失败就返回SOCKET_ERROR,需要通过WSAGetLastError获得进一步的错误信息.

#define SOCKET_ERROR            (-1)
实际上是 0xFFFFFFFF 4bytes

send() sendto()

如果成功就返回发送的字节数,如果失败就返回SOCKET_ERROR,需要通过WSAGetLastError获得进一步的错误信息.

recv() recvfrom()

如果成功就返回收到的字节数,如果如果失败就返回SOCKET_ERROR,需要通过WSAGetLastError获得进一步的错误信息.

如果连接被温和的关闭,返回0,但是recvfrom通常是用于无连接的UDP socket.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值