搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
羊村懒王
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
前端技术都有哪些?_具体的前没技术
2
OpenCV结合V4l2实现人脸检测_v4l2支持人脸识别么
3
七大数据分析模型详解,做分析不再没思路_数据量化分析模型
4
Android error: JNI DETECTED ERROR IN APPLICATION_android jni detected error in application: use of
5
最后的一个你问offer机会-恒玄科技【IS3GJJ】_新和成万华
6
KETTLE文本文件输入_kettle 配置文件输入
7
注意力机制、Transformer模型、生成式模型、目标检测算法、图神经网络、强化学习、深度学习模型可解释性与可视化方法等详解_使用可解释的模型架构,如具有注意力机制的模型,以及通过可视化工具和技术来解释网
8
开发人员面试62到经典题
9
python SNMP 网段指定community进行扫描,返回 json PySNMPScan_snmp 返回raw
10
IP地址计算---子网掩码确定和子网划分等详解 (附常见相关习题)_子网掩码计算例题和讲解
当前位置:
article
> 正文
Winsock API 编程介绍_简述winsock2api编程基本模型
作者:羊村懒王 | 2024-02-26 20:57:47
赞
踩
简述winsock2api编程基本模型
相信很多人都对网络编程感兴趣,下面我们就来介绍,在网络编程中应用最广泛的编程接口WinSock API。
使用WinSock API的编程,应该了解一些TCP/IP的基础知识。虽然你可以直接使用WinSock API来写网络应用程序,但是,要写出优秀的网络应用程序,还是必须对TCP/IP协议有一些了解的。
1、TCP/IP协议与WinSock网络编程接口的关系
在开始之前,我们先说一下WinSock和TCP/IP到底是什么关系。
我碰到很多人问我:怎样使用WinSock协议编程?其实,这话说的有点错误,WinSock并不是一种网络协议,他只是一个网络编程接口,也就是说,他不是协议,但是他可以访问很多种网络协议,你可以把他当作一些协议的封装。现在的WinSock已经基本上实现了与协议无关。你可以使用WinSock来调用多种协议的功能。
那么,WinSock和TCP/IP协议到底是什么关系呢?实际上,WinSock就是TCP/IP协议的一种封装,你可以通过调用WinSock的接口函数来调用TCP/IP的各种功能.例如我想用TCP/IP协议发送数据,你就可以使用WinSock的接口函数Send()来调用TCP/IP的发送数据功能,至于具体怎么发送数据,WinSock已经帮你封装好了这种功能。
2、TCP/IP协议介绍
现在来介绍一些TCP/IP的原理。TCP/IP协议包含的范围非常的广,他是一种四层协议,包含了各种硬件、软件需求的定义,我们这里只介绍软件方面的知识。TCP/IP协议确切的说法应该是TCP/UDP/IP协议。
UDP协议(User Datagram Protocol 用户数据报协议),是一种保护消息边界的,不保障可靠数据的传输。
TCP协议(Transmission Control Protocol 传输控制协议),是一种流传输的协议。他提供可靠的、有序的、双向的、面向连接的传输。
3、保护消息边界和流
那么什么是保护消息边界和流呢?
保护消息边界,就是指传输协议把数据当作一条独立的消息在网上传输,接收端只能接收独立的消息。也就是说存在保护消息边界,接收端一次只能接收发送端发出的一个数据包。
而面向流则是指无保护消息保护边界的,如果发送端连续发送数据,接收端有可能在一次接收动作中,会接收两个或者更多的数据包。
我们举个例子来说,例如,我们连续发送三个数据包,大小分别是2k、4k、8k,这三个数据包都已经到达了接收端的网络堆栈中,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有三次接收动作,才能够把所有的数据包接收完。而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们就能够一次把所有的数据包接收下来,只需要有一次接收动作。
这就是因为UDP协议的保护消息边界使得每一个消息都是独立的。而流传输,却把数据当作一串数据流,他不认为数据是一个一个的消息。所以有很多人在使用TCP协议通讯的时候,并不清楚TCP是基于流的传输,当连续发送数据的时候,他们时常会认识TCP会丢包。其实不然,因为当他们使用的缓冲区足够大时,他们有可能会一次接收到两个甚至更多的数据包,而很多人往往会忽视这一点,只解析检查了第一个数据包,而已经接收的其他据包却被忽略了。所以大家如果要作这类的网络编程的时候,必须要注意这一点。
4、WinSock编程简单流程
下面我们介绍一下Win32平台的WinSock编程方法。
通讯必须有服务器端和客户端。我们简单介绍TCP服务器端的大体流程。
对于任何基于WinSock的编程首先我们必须要初始化WinSock DLL库。
int WSAStarup( WORD wVersionRequested,LPWSADATA lpWsAData )。
wVersionRequested是我们要求使用的WinSock的版本。
调用这个接口函数可以帮我们初始化WinSock 。然后我们必须创建一个套接字(Socket)。
SOCKET Socket(int af,int type,int protocol);
套接字可以说是WinSock通讯的核心。WinSock通讯的所有数据传输,都是通过套接字来完成的,套接字包含了两个信息,一个是IP地址,一个是Port端口号,使用这两个信息,我们就可以确定网络中的任何一个通讯节点。
当我们调用了Socket()接口函数创建了一个套接字后,我们必须把套接字与你需要进行通讯的地址建立联系,我们可以通过绑定函数来实现这种联系。
int bind(SOCKET s,const struct sockaddr FAR* name,int namelen) ;
struct sockaddr_in{
short sin_family ;
u_short sin_prot ;
struct in_addr sin_addr ;
char sin_sero[8] ;
}
就包含了我们需要建立连接的本地的地址,包括地址族、IP和端口信息。sin_family字段我们必须把他设为AF_INET,这是告诉WinSock使用的是IP地址族。sin_prot就是我们要用来通讯的端口号。sin_addr就是我们要用来通讯的IP地址信息。
在这里,必须还得提一下有关'大头(big-endian)'小头(little-endian)'。因为各种不同的计算机处理数据时的方法是不一样的,Intel X86处理器上是用'小头'形式来表示多字节的编号,就是把低字节放在前面,把高字节放在后面,而互联网标准却正好相反,所以,我们必须把主机字节转换成网络字节的顺序。WinSock API提供了几个函数。
把主机字节转化成网络字节的函数;
u_long htonl(u_long hostlong);
u_short htons(u_short hostshort);
把网络字节转化成主机字节的函数;
u_long ntohl(u_long netlong);
u_short ntohs(u_short netshort) ;
这样,我们设置IP地址和port端口时,就必须把主机字节转化成网络字节后,才能用Bind()函数来绑定套接字和地址。
当绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。
int listen(SOCKET s,int backlog);
这个函数可以让我们把套接字转成监听模式。
如果客户端有了连接请求,我们还必须使用
int accept(SOCKET s,struct sockaddr FAR* addr,int FAR* addrlen);
来接受客户端的请求。
现在我们基本上已经完成了一个服务器的建立,而客户端的建立的流程则是初始化WinSock,然后创建Socket套接字,再使用
int connect(SOCKET s,const struct sockaddr FAR* name,int namelen) ;
来连接服务端。
下面是一个最简单的创建服务器端和客户端的例子:
服务器端的创建:
WSADATA wsd;
SOCKET sListen;
SOCKET sclient;
UINT port = 800;
int iAddrSize;
struct sockaddr_in local , client;
WSAStartup( 0x11 , &wsd );
sListen = Socket ( AF_INET , SOCK_STREAM , IPPOTO_IP );
local.sin_family = AF_INET;
local.sin_addr = htonl( INADDR_ANY );
local.sin_port = htons( port );
bind( sListen , (struct sockaddr*)&local , sizeof( local ) );
listen( sListen , 5 );
sClient = accept( sListen , (struct sockaddr*)&client , &iAddrSize );
客户端的创建:
WSADATA wsd;
SOCKET sClient;
UINT port = 800;
char szIp[] = "127.0.0.1";
int iAddrSize;
struct sockaddr_in server;
WSAStartup( 0x11 , &wsd );
sClient = Socket ( AF_INET , SOCK_STREAM , IPPOTO_IP );
server.sin_family = AF_INET;
server.sin_addr = inet_addr( szIp );
server.sin_port = htons( port );
connect( sClient , (struct sockaddr*)&server , sizeof( server ) );
当服务器端和客户端建立连接以后,无论是客户端,还是服务器端都可以使用
int send( SOCKET s,const char FAR* buf,int len,int flags);
int recv( SOCKET s,char FAR* buf,int len,int flags);
函数来接收和发送数据,因为,TCP连接是双向的。
当要关闭通讯连结的时候,任何一方都可以调用
int shutdown(SOCKET s,int how);
来关闭套接字的指定功能。再调用
int closeSocket(SOCKET s) ;
来关闭套接字句柄。这样一个通讯过程就算完成了。
注意:上面的代码没有任何检查函数返回值,如果你作网络编程就一定要检查任何一个WinSock API函数的调用结果,因为很多时候函数调用并不一定成功。上面介绍的函数,返回值类型是int的话,如果函数调用失败的话,返回的都是SOCKET_ERROR。
5、WinSock编程的模型
上面介绍的仅仅是最简单的WinSock通讯的方法,而实际中很多网络通讯的却很多难以解决的意外情况。
例如,WinSock提供了两种套接字模式:锁定和非锁定。当我们使用锁定套接字的时候,我们使用的很多函数,例如accpet、send、recv等等,如果没有数据需要处理,这些函数都不会返回,也就是说,你的应用程序会阻塞在那些函数的调用处。而如果使用非阻塞模式,调用这些函数,不管你有没有数据到达,他都会返回。所以有可能我们在非阻塞模式里,调用这些函数大部分的情况下会返回失败,所以就需要我们来处理很多的意外出错。
这显然不是我们想要看到的情况。我们可以采用WinSock的通讯模型来避免这些情况的发生。
WinSock提供了五种套接字I/O模型来解决这些问题。他们分别是select(选择),WSAAsyncSelect(异步选择),WSAEventSelect (事件选择,overlapped(重叠) , completion port(完成端口) 。
我们在这里详细介绍一下select,WSAASyncSelect两种模型。
Select模型是最常见的I/O模型。
使用
int select( int nfds , fd_set FAR* readfds , fd_set FAR* writefds,fd_set FAR* exceptfds,const struct timeval FAR * timeout ) ;
函数来检查你要调用的Socket套接字是否已经有了需要处理的数据。
select包含三个Socket队列,分别代表:
readfds ,检查可读性,writefds,检查可写性,exceptfds,例外数据。
timeout是select函数的返回时间。
例如,我们想要检查一个套接字是否有数据需要接收,我们可以把套接字句柄加入可读性检查队列中,然后调用select,如果,该套接字没有数据需要接收,select函数会把该套接字从可读性检查队列中删除掉,所以我们只要检查该套接字句柄是否还存在于可读性队列中,就可以知道到底有没有数据需要接收了。
WinSock提供了一些宏用来操作套接字队列fd_set。
FD_CLR( s,*set) 从队列set删除句柄s。
FD_ISSET( s, *set) 检查句柄s是否存在与队列set中。
FD_SET( s,*set )把句柄s添加到队列set中。
FD_ZERO( *set ) 把set队列初始化成空队列。
WSAAsyncSelect(异步选择)模型:
WSAASyncSelect模型就是把一个窗口和套接字句柄建立起连接,套接字的网络事件发生时时候,就会把某个消息发送到窗口,然后可以在窗口的消息响应函数中处理数据的接收和发送。
int WSAAsyncSelect( SOCKET s, HWND hWnd , unsigned int wMsg , long lEvent ) ;
这个函数可以把套接字句柄和窗口建立起连接,
wMsg 是我们必须自定义的一个消息。
lEvent就是制定的网络事件。包括FD_READ , FD_WRITE , FD_ACCEPT,FD_CONNECT,FD_CLOSE 。
几个事件。
例如,我需要接收FD_READ , FD_WRITE , FD_CLOSE 的网络事件。可以调用
WSAAsyncSelect( s , hWnd , WM_SOCKET , FD_READ | FD_WRITE | FD_CLOSE ) ;
这样,当有FD_READ , FD_WRITE 或者 FD_CLOSE网络事件时,窗口hWnd将会收到WM_SOCKET消息,消息参数的lParam标志了是什么事件发生。
其实大家应该见过这个模型,因为MFC的CSocket类,就是使用这个模型。
上面为大家介绍了WinSock编程的一些方法。当然,WinSock编程远不止这些知识,如果想要学好网络编程,还是需要不断的学习和研究的
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/羊村懒王/article/detail/147043?site
推荐阅读
article
牛客——
华为
机试
_
华为
机试
合唱队
python
解析...
T15. 求int型数据在内存中存储时1的个数#include
using namespace st...
赞
踩
article
Centos
开启
防火墙
开放
端口
_
centos
防火墙
端口
开放...
查看指定接口所属区域: firewall-cmd --get-zone-of-interface=eth0。查看所有打开...
赞
踩
article
Unity XR
Interaction
Toolkit
(二)
手柄
交互_
unity
手柄
按键
事件
...
XR
Interaction
手柄
事件
和抓取设置_
unity
手柄
按键
事件
unity
手柄
按键
事件
...
赞
踩
article
力扣热题
100
---
栈...
1.有效的括号给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。有效字...
赞
踩
article
基于
java
的运动健康
微信
小
程序
_
java
微信
小
程序
步数
...
开发工具(eclipse/idea/vscode等):eclipse。数据库(sqlite/mysql/sqlserve...
赞
踩
article
基于
Java
+
SpringBoot
+
Vue
前后端分离
仓库
管理
系统
设计实现_
仓库
管理
后端接口案例...
仓库
管理
系统
进行了字典
管理
、公告
管理
、用户
管理
、物资
管理
、物资申请
管理
、
仓库
员
管理
、统计报表等服务。设备采用关联数据库里...
赞
踩
article
linux
下
root
密码找回
方法集锦...
linux
下
root
密码找回
方法集锦[url]http://xbbian.blog.hexun.com/18498548...
赞
踩
article
InputStream
/
OutputStream
---
读写
文件
_读取
outputstream
的
内容
...
文件
读
文件
import java.io.File;import java.io.File
InputStream
;impo...
赞
踩
article
微信
小
程序
配置
服务器
域名
端口
_
微信
小
程序
要用
哪些
端口
...
微信
小
程序
配置
服务器
域名
端口
_
微信
小
程序
要用
哪些
端口
微信
小
程序
要用
哪些
端口
1.可以
配置
端口
,如...
赞
踩
article
matlab
log
函数
_
matlab
中
log
函数
怎么写...
通常所说的
log
是指以10为底的对数,而MATLAB中的
log
却不是这样。Matlab中的
log
函数
在默认情况下是以e为...
赞
踩
article
网络
编程
socket
(上)_
socket
可以
绑定
两个
端口
吗...
socket
通信本质通过IP地址和MAC地址能够将数据发送到对端主机了,但实际上是想将数据发送给对端主机上的某个服务进程...
赞
踩
article
CentOS
防火墙
查看设置
开放
端口
_
centos
查看
防火墙
开放
端口
...
linux
防火墙
开放
端口
_
centos
查看
防火墙
开放
端口
centos
查看
防火墙
开放
端口
1.查看...
赞
踩
article
PACS
系统
源码
PACS
源码
基于VC +
MSSQL
开发...
PACS
系统
可以覆盖医院现有放射、CT、MR、核医学、超声、内镜、病理、心电等绝大部分DICOM和非DICOM检查设备,...
赞
踩
article
Unity
简单
实现
JoyStick
摇杆
,
小学生能看懂系列_
unity
joystick
教程...
嘿欢迎点开小熊的博客
,
让我们继续前行吧!40行
实现
主要内容。*提供工程样例
,
在本文最后。效果图片:原理解析:布局思路:C...
赞
踩
article
【
Linux
】
Shell
详解
_
linux
shell
是
什么意思...
【
Linux
】
Shell
详解
_
linux
shell
是
什么意思
linux
shell
是
什么意思 ...
赞
踩
article
SOCKET
网络程序设计_
socke
网络程序设计...
实验原理 1、关于使用套接字编程的一些基本概念 (a)半相关与全相关 半相关 在网络中用一个三元组可以在...
赞
踩
article
物联网应用入门--利用虚拟硬件模拟
土壤湿度
传感器
应用编写_1
、
使用
虚拟仿真
进行
完成
考试内容
:
有线传感...
探测
土壤水分
Sketchnote by Nitya Narasimhan. Click the image for a ...
赞
踩
article
每天
一个
知识点
- 常用
设计模式
...
每天
一个
知识点
- 常用
设计模式
每天
一个
知识点
- 常用
设计模式
设计原则 单一职责原则 对类来...
赞
踩
article
机器
学习
笔记...
对
机器
学习
的定义: Machine Learning is Fields of study that gives com...
赞
踩
article
基于
DCT
系数
关系的
图像
水印
算法...
1、
DCT
域的
图像
水印
嵌入与提取在信号的频域(变换域)中隐藏信息要比在时域中嵌入信息具有更好的鲁棒性。一副
图像
经过时域到...
赞
踩
相关标签
算法
centos
linux
运维
unity
vr
xr
交互
leetcode
java
面试
数据库
开发语言
Java
SpringBoot
仓库管理系统
vue
大学生项目实战
服务器
前端
https
log
matlab
网络