network socket (c++) 译文(3)

原文链接:http://www.madwizard.org/programming/tutorials/netcpp/3

翻译:

Sockets and winsock

Winsock(‘windows sockets’)是处理网络的Windows API。很多函数的执行方法和BSD Unix中的Berkeley socket的函数相同。

1. Socket

什么是套接字(socket)?

1 

几乎所有的WINSOCK函数都是在socket上执行的。它是你连接的句柄。连接的两端都有一个socket。而且它们并没有指定平台。(例如一个Windows 和一个Unix的机器就可以通过socket进行通信)。sockets也是双向的通信的,所以数据可以在同一个socket上收发。

一个socket有两种常用的类型。一种是流式套接字(SOCK_STREAM)另一个是数据包式套接字(SOCK_DGRAM)。流式变体是为需要可靠连接的应用而设计,通常使用连续的数据流。这种类型的socket使用的协议的TCP。本教程中只是用这种套接字,因为它广泛用于我们熟悉的HTTP, TCP, SMTP,POP3等协议。

而数据报式套接字使用UDP作为基础协议,是面对无连接的。它有一个最大缓存长度值。它们主要是用于发送小数据包且对可靠性要求不高的应用。与流式套接字不同的是,数据包式套接字并不需要保证数据将到达目的地或者到达的顺序是正确的。数据报式套接字用于像流音频、流视频等应用会稍微更快更有效果。但是可靠性的优先权却不如速度和潜在因素高。所以对可靠性有要求的地方使用流式套接字。

2. Binding sockets

绑定(Binging)一个 套接字就是将一个特定的地址(IP地址和端口号)与一个给定的套接字相关联。可以通过bind函数手动完成。但是在一些情况下,WINSOCK将自动绑定套接字。这个在下一章中会说明。

3. Connecting

你使用套接字的方式取决于你是在客户端还是服务器端。客户端通过创建一个套接字,并调用含特定的地址信息connect函数,会发起一个连接请求。在这个套接字建立连接之前,它还没有绑定一个IP地址和端口号。因为客户端可以使用任意IP地址和端口号与服务器端建立连接(假设这些IP地址均是能到达目的地网络IP地址),通常可能建立很多可用的连接。

connect函数被调用后,在正在建立连接之前,WINSOCK将会选择一个IP地址和一个端口号用于连接和绑定客户端的这个套接字。这个端口号是此时任意可用的端口号。但是IP号需要注意一点:一台电脑不止一个IP地址。例如:一台PC同时连在互联网和本地网络中,那么它至少有3个IP号。(一个外部IP用于Internet,本地IP(192.168.x.x或10.0.x.x等))还有环回地址(127.0.0.1)。这里选择哪个个IP号去绑定套接字是很重要的,因为它也会决定你用于连接的网络。如果你想连接本地PC 192.168.0.4,你不能使用你的Internet IP地址。因为192.168.0.4这个IP在Internet中不能找到。因此你必须使用同网络中的IP地址绑定你的套接字(如192.168.0.1)。同样的,如果你将环回地址(127.0.0.1)绑定你的套接字,那么你就只能连接同样地址(127.0.0.1)的套接字,而不能连接其他的任何IP地址。

幸运的是,WINSOCK会自动选择一个可用的IP地址。你自己绑定socket,没有任何问题。但是记住你需要考虑上面所述的情形。

记住:bind函数提供给用户设置IP和端口的选择。端口号可以设置为0。端口号为0的意思是让WINSOCK自动选择一个端口号。这有利于当你处于客户端很想使用某一特定的IP地址进行连接时,不需要考虑端口号是否可用。

4. Listening

在服务器端,情况就跟客户端不一样了。一个服务器需要等待进来的连接请求。而且客户端需要知道服务器的IP地址和端口号才能进行连接服务器。为了方便起见,一般服务器需要固定一个端口号(通常默认的端口号给了使用的协议。)

在特定的地址上等待连接请求叫做监听(listening):

2 

从上面的定义可以看出,套接字进入监听状态之前,需要绑定地址。当这个地址中设定了固定端口号之后,服务器将只监听从这个端口号进来的连接请求。例如,大多数的网站服务器只监听端口号80(HTTP的默认值)。套接字也可以绑定特定的IP号,但是如果邦定地址中的IP号设置为0时,套接字就可以在任意可用的地址上监听,这样有效地在整个网络上均能建立连接。可设置固定的IP号来绑定套接字,例如本地网络接口,这样本地网络中的电脑可以连接到服务器。但是它不是直接通过Internet建立连接的。

当一个客户端请求监听服务器建立一个连接时,服务器将会接受(accept)请求(或者拒绝)。并且创建一个新的套接字作为连接的一段。这样,处于监听状态的套接字没有被占用于连接中的数据传输,而是继续监听更多进来的连接请求。

5. Connetions: an example

下面是关于网站服务器处理多连接请求的图解例子:

(1)  创建服务器套接字:

3

服务器端创建一个新的套接字。当它创建完时,并没有绑定IP地址和端口号;

(2)  绑定服务器套接字

4

因为服务器是一个网站服务器。你需要绑定端口号80,这个HTTP的默认端口号。但是IP地址被设置为0。这表明服务器在它所运行的机器上,将会接受来自任意可用IP地址的连接请求。在这个例子中,我们假设服务器有3个IP地址,一个是外网IP地址(216.239.39.101),一个是内网IP地址(192.168.0.8),当然还有一个环回地址(127.0.0.1)。

(3)  服务器进入监听状态

5当套接字绑定后,套接字进入监听状态。等待从80端口号进来的连接请求。

(4)  客户端创建一个套接字

6假设一个客户端在同一个局域网内,服务器为(192.168.x.x),想要向服务器请求一个网页。为了传输数据,客户端需要创建一个套接字。

(5)  客户端套接字发起连接请求

    7左边的客户端套接字没有绑定,试着连接网站服务器。

(6)  客户端接受连接请求

 8

监听套接字看到客户端想要建立连接。监听套接字通过创建一个新的套接字(右下)接受连接请求。这个新的套接字绑定了一个客户端能到达的服务器IP地址。(他们在同一局域网内,服务器IP为192.168。x.x)且服务器端口为80。从这一点,客户端和服务器刚被创建的套接字可以进行数据传输了。同时监听套接字将继续监听其他的连接请求。注意:由于建立连接,此时客户端的套接字是绑定了IP和端口的。图中黑色虚点线是为了分开客户端与服务器端的。

(7)  有一个客户端发起连接请求

 9

如果外网有一个客户端想建立连接,服务器将会又一次的创建一个新的套接字来处理第二次的连接。注意:服务器端套接字绑定的IP地址与上一次连接的不同。这是可能的。因为监听套接字并没有绑定任何的IP地址。如果监听套接字绑定了192.168.0.8,则第一次连接将不能建立。

6. Blocking

在Berkeley unix上执行套接字的原始函数是封闭的函数。即如果所需的操作不能立刻完成时,这些封闭函数将只能等待。例如,向服务器端发起连接请求时调用connect函数。connect函数不会立刻返回,直到连接建立(或者连接失败)。因此需要将程序中止一会。在Windows环境下使用一个控制台模式应用来处理单个连接实际上没有问题。但是我们一般不允许这么做。任何带窗口的程序都有一个一直运行的窗口程序。当使用套接字函数时,停止窗口程序将会延迟用户的输入,窗口绘画,通知还有应用产生的其他信息等。看起来好像程序被悬挂起来了。

为了解决这个问题,WINSOCK可以设置套接字进入封闭或者非封闭模式。封闭模式是按原来的方法使用套接字。即操作完成之前,函数不从API返回(字面理解就是把应用程序阻塞了)。而我们通常处理Windows应用程序(而不是控制台程序)时用到的就是非封闭模式。当调用一个关于SOCKET的非封闭模式函数时,即使所需执行的操作不能立刻完成,该函数将尽可能快的返回。反而,当操作结束时,某种类的通知会发送到程序。这样操作没有完成之前,允许程序正常执行。

WINSOCK为非封闭的套接字提供几种方式的通知,包括窗口信息,事件对象。这些方式将在后面详细讨论。现在只需要记住封装模式与非封装模式的不同。

7. Winsock versions

Winsock最常用的版本是2.x,由于这些版本差别不大,所以统称作Winsock 2。版本2之前的最新版本是版本1.1。有人说你考虑到兼容性问题,应该使用版本1.1因为Windows 95和NT只支持版本1.1.但是Windows后来出的版本(98,ME,NT4,2000,和XP)都默认为版本2,而Windows 95可以更新。因此,我推荐你直接用WINSOCK2,它比版本1.1增加了更多很好的特点,不带WINSOCK 2的Windows机器几乎很少。

Winsock两个只要的版本属于不同的DLLs(动态链接库),版本1.1,和版本2.x各自的DLL为wsock32,dllws2_32.dll。相应的库函数为wsock32.libws2_32.lib。在MASM32工具包的windows,inc中有很多的WINSOCK的常量。对于C++程序来说,只需要包含windows.h就足够用了。因为_WIN32_WINNT版本号不小于0x400(NT的版本号是4)时Windows.h头文件包含了winsock 2.h文件。Winsock 2 API包含了整个1.1版本的API(修改的地方很少),对于实际的winsock ws2_32.Dll来说wsock32.dll只是它们包装盒。

本教程将只是用WINSOCK 2。

8. Winsock architecture

WINSOCK 提供两个接口,应用程序接口(API)和服务提供者接口(SPI)。本教程只关于API,它包括通信所需所有常规协议的函数。SPI是加在数据传输供应商(TCP/IP,IPX/SPX)上的接口或者是域名空间服务供应商(像DNS)。这些扩展对于使用API用户来说是透明的。

 

原文链接: https://www.cnblogs.com/xiaozhupp/archive/2013/05/02/3055622.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    network socket (c++) 译文(3)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/86776

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午10:46
下一篇 2023年2月9日 下午10:47

相关推荐