`
sabolasi
  • 浏览: 908357 次
文章分类
社区版块
存档分类
最新评论

套接字socket及C/S通信的基本概念

 
阅读更多

一.套接字Socket基本概念

WinSock(Windows Sockets)是处理网络通信的Windows API。许多函数与在BSD中使用的Berkely套接字函数是相同的。套接字,简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程。

应用层通过传输层进行数据通信时,TCPUDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。

区分不同应用程序进程间的网络通信和连接,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCPUDP)和使用的端口号。Socket原意是插座,通过将这3个参数结合起来,与一个插座”Socket绑定,应用层就可以和传输层通过套接字接口区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

每一个基于TCP/IP网络通讯的程序(进程)都被赋予了唯一的端口(号),端口是一个信息缓冲区,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数(unsigned short),范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于1024的端口号保留给标准应用程序,比如pop3的端口号就是110。每一个套接字都组合进了IP地址、端口、端口号,这样形成的整体就可以区别每一个套接字。

Socket可以看成在两个程序进行通讯连接中的一个端点(endpoint,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。一般一个server服务器对应很多客户端client连接,服务器必须维护一张客户连接列表,每增加一个客户端连接服务器端都要新建一个套接字负责与新增客户端进行对话通信。

传输套接字主要有两类:流式套接字(SOCK_STREAM)和数据报套接字(SOCK_DGRAM)。流类型的套接字是为需要可靠连接的应用程序设计的。这些程序通常使用连续的数据流。用于这种类型套接字的协议是TCP,适合FTP这类实现。流套接字是最常用的,一些众所周知的协议如HTTPTCPSMTPPOP3等都是基于面向流的协议。

数据报套接字使用UDP做为下层协议,是无连接的,有一个最大缓冲区大小(数据包大小的最大值)。它是为那些需要发送小数据包,并且对可靠性要求不高的应用程序设计的。与流式套接字不同,数据报套接字并不保证数据会到达终端,也不保证它是以正确的顺序到来的。数据报套接字的传输效率相当高,它经常用于音频或视频应用程序。对这些程序来说,速度比可靠性更加重要。

二.基于套接字的C/S通信模式

以下为基于SocketC/S通信模式图:

关于服务器端监听套接字和accept返回的新的套接字的区别

一个连接由(server_ip, server_port)和(client_ip, client_port)唯一确定。你可以调用getsockname()函数获取与某个套接字关联的本地地址,调用getpeername()函数获取与某个套接字关联的目的地址。

关于监听套接字和accept()返回的新的套接字的区别,借用以下情景说明。好比你去吃饭,饭馆门迎小姐(监听SOCKET)看到你来后和你打招呼,然后(ACCEPT)找来一个服务员小姐(NEW SOCKET)伺候你,然后守在门口继续欢迎(监听)下一个。当然门迎小姐会记录是哪一位服务员小姐招待了你;如再有新客人来,门迎小姐(同一监听SOCKET)又会安排另一位服务员小姐(NEW SOCKET)伺候。门迎小姐走了,伺候每一位客人的服务员小姐不受影响。从以上情景可知连接建立后,客户端用发出连接的那个SOCKET向服务器发数据,是发给服务器新创建的SOCKET,而不是服务器的监听SOCKET。服务器的监听SOCKET永远只是用来接受连接请求。

三.套接字的两种模式

套接字有阻塞(锁定)和非阻塞(非锁定)两种模式。非阻塞和阻塞描述的是WinSock API调用行为特性。

1)阻塞模式套接字

在一个阻塞套接字上调用任何WinSock API函数(accept()/recv()/send()),都会耗费或长或短的时间等待返回,这会阻塞调用线程。直到有点数据可读或可写时,这种调用才返回。

阻塞模式的优点是符合时序,容易入手。缺点也是显而易见的,假设这样一种情景,一个线程中要处理多个客户(套接字AB),我们在套接字AB上顺序调用recv企图依次接收数据。若客户A始终不发数据,则recv(A)函数将可能永远无法返回,在这期间我们错失了客户B发送来的数据。

大多数WinSock应用都遵循生产者-消费者模型,应用程序需要读取(或写入)指定数量的字节,然后再对读取的数据执行一些计算。在应用程序中,可以为每个套接字都创建一个负责读取网络数据的读线程(ReadThread),以及一个负责对数据执行计算的数据处理线程(ProcessThread)。尽管这会增大一些开销,但的确是一种可行的方案。缺点便是扩展性极差,而且无法应对大规模的通信情况。

2)非阻塞模式套接字

将一个套接字置为非阻塞模式之后,WinSock API调用会立即返回。大多数情况下,这些调用都会失败SOCKET_ERROR),并返回一个WSAEWOULDBLOCK错误。它意味着请求的操作在调用期间没有时间完成。举个例子来说,假如在系统的输入缓冲区中,尚不存在待决的数据,那么recv()调用就会返回WSAEWOULDBLOCK错误。通常,我们需要重复调用同一个函数,直至获得一个成功返回代码。

假如需要编写更多的代码,以便在每个 Winsock调用中,对收到一个WSAEWOULDBLOCK错误的可能性加以应付,那么非阻塞套接字便显得有些难于操作。在这些情况下,可考虑使用套接字I/O模型,它管理I/O完成通知,帮助应用程序判断套接字何时可供读写。

四.同步I/O和异步I/O

套接字模式讨论的是套接字函数的调用特性,而I/O模型讨论的是调用背后的行为特性。

CPU执行代码(当前活动线程)时遇上一个I/O请求(例如调用ReadFile()/WriteFile()recv()/send())时,系统产生一个中断,当前活动线程阻塞在此,让CPU去完成这个I/O请求,等到完成后,系统再次产生一个中断让原先的程序继续运行。也就说通过中断保持这两者间的同步,可以将终端理解为硬件化的信号量。

这就是所谓的同步I/O,一个线程中只可能同时处理一个I/O请求。因为一个I/O操作是非常耗时的,所以代码挂起后等待I/O完成的这段时间内,这个线程浪费了很多个指令周期。如果要同时反复读写大文件,则同步I/O的效率是很低的。

当然,可以考虑使用多线程来处理。例如在设计服务器时可以使用多线程来处理客户请求,每有一个客户连接请求,就创建一个新线程,专门处理它的通信请求。对于小型服务器来说,这不是问题。对于同时处理成千上万个请求的大型服务器而言,使用多线程是无效的,因为系统能够支持的线程数量毕竟是有限制的。另外一种解决方案就是使用共享负载的线程池,这涉及到异步I/O

在异步I/O中,当CPU执行你的代码遇上一个I/O请求时,使用一个线程去处理I/O请求,并且当前调用线程并不挂起。如果后续代码和这个I/O有关(例如需要等待I/O操作的结果),那么它就要等到这个I/O操作完成。通常在一个线程中调用WaitForSingleObject/WaitForMultipleObjectsWSAWaitForMultipleEvents(WSA)GetOverlappedResult等函数就可以得到I/O完成的消息,然后再对数据进行处理。但如果后续的代码和这个I/O操作无关,你就可以以更快的速度执行下去了,而无需等待I/O请求的完成了。这就是异步I/O了。

关于同步和异步,参考以下实例:

举例1:手机的通讯

手机打电话时同步,发短信是异步。

举例2:请你吃饭

同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。

异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。

举例3Windows消息处理

SendMessage同步:把一条消息投放到创建hWnd窗口的线程的消息队列中,直到消息被处理完毕才返回。

PostMessage异步:把一条消息投放到创建hWnd窗口的线程的消息队列中,不等消息被处理就立即返回。

举例4B/S交互

普通B/S模式同步:提交请求等待服务器处理(这期间客户浏览器不能干任何其他事情)处理完毕返回。

AJAX技术异步: 请求通过事件触发服务器处理(这期间浏览器仍然可以作其他事情)处理完毕。

参考

Windows 2000 Systems Programming Black Book Al Williams

Network Programming for Microsoft Windows Anthony Jones,Jim Ohlund

struct socket详解

FreeBSD 开发手册

同步和异的区别

网络编程中的异步、同、阻塞、非阻塞的理解

分享到:
评论

相关推荐

    通过socket实现webservice的功能.rar

    Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求, Socket本质是编程接口(API),是对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;...

    MFC网络编程之自制浏览器

    网络编程,当然要用到Windows Socket(套接字)技术。Socket相关的操作由一系列API函数来完成,比如socket、bind、listen、connect、accept、send、sendto、recv、recvfrom等。调用这些API函数有一定的先后次序,有些...

    用C自己编写端口扫描软件

    为通信连接创建一个套接字 af参数: 指定套接字地址格式,在winsock中只能使用AF_INET type参数: 套接字类型,这里使用了SOCK_STREAM,流套接字 protocol参数:配合type使用,指定协议类型,这里使用IPPROTO_TCP...

    Linux Socket编程入门——浅显易懂

    网络套接字API函数 5.1 socket() 5.2 bind() 5.3 listen() 5.4 accept() 5.5 connect()6. 一个简单的C/S模型代码实例7.总结 1. 概述   网络通信,首先那些七层模型等概念,小的不才,之前有写过几...

    从零开始学Python第八周:详解网络编程基础(socket)

    套接字是一个双向的通信信道的端点。套接字可能在沟通过程,进程之间在同一台机器上,或在不同的计算机之间的进程 要创建一个套接字,必须使用Socket模块的socket.socket()方法 在socket模块中的一般语法: s = ...

    深入分析Linux内核源码

    12.4.2 套接字缓冲区操作基本原理 12.4.3 sk_buff数据结构的核心内容 12.4.4 套接字缓冲区提供的函数 12.4.5 套接字缓冲区的上层支持例程 12.5 网络设备接口 12.5.1 基本结构 12.5.2 命名规则 12.5.3 设备...

    Visual C#网络编程技术与实践源代码

    全书共分13章,主要内容包括网络编程原理、Visual C# 2005的套接字以及多线程的开发、基于各种不同协议的网络编程应用模块,并通过几个典型的实例介绍了Visual C# 2005网络编程的实际应用。 本书注重代码的通用性和...

    c# 加密和解密相关代码

    在实现本实例之前先来简要了解一下加密的概念,加密是指通过 某种特殊的方法,更改已有信息的内容,使得未授权的用户即使得到 了加密信息,如果没有正确解密的方法,也无法得到信息的内容。谈 到加密的话题,一些...

    Java开发技术大全 电子版

    3.1面向对象的基本概念98 3.1.1对象98 3.1.2类99 3.1.3消息101 3.1.4面向对象的4个基本特征101 3.2类与对象104 3.2.1类的基本结构104 3.2.2类的声明104 3.2.3创建类体105 3.2.4对象的生命周期106 3.2.5...

    linux网路编程 中文 23M 版

    2.2 Linux下的G C C 编译器工具集.......................................... 19 2.2.1 G C C 简介......................................................19 2 . 2 . 2 编译程序的基本知识.........................

    新版Android开发教程.rar

    Android Android Android Android 手机新概念 操作系统的选择 -------- 定制和长尾 � 重构 � MVC 和 Web APP 架构 Android Android Android Android 开发背景 � 计算技术、无线接入技术的发展,使嵌入式系统逐渐...

Global site tag (gtag.js) - Google Analytics