套接字
多个TCP连接或多个应用程序 进程可能需要通过同一个 TCP协议 端口传输数据。为了区别不同的应用程序 进程和连接,许多计算机操作系统 为应用程序与TCP/IP协议 交互提供了称为套接字(Socket)的接口。
目 录
1 分类
2 简介
3 连接方式
4 主要参数
5 分类介绍
6 Sockets
7 注意
8 运行示例
9 示例
10 关键字
11 通信
1 分类
常用的TCP/IP协议 的3种套接字类型如下所示。 流套接字(SOCK_STREAM): 流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议 ,即TCP(The Transmission Control Protocol)协议 。 数据报套接字(SOCK_DGRAM):数据报套接字提供了一种无连接 的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP(User Datagram Protocol)协议 进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。 原始套接字(SOCK_RAW):原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核 没有处理的IP数据包,而流套接字只能读取TCP协议 的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议 发送数据必须使用原始套接字。
2 简介
套接字,是支持TCP/IP 的网络通信 的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。 非常非常简单的举例说明下:Socket=Ip address+ TCP/UDP + port。
3 连接方式
应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序 进程提供并发服务的问题。
4 主要参数
区分不同应用程序 进程间的网络通信 和连接,主要有3个参数:通信的目的IP地址、使用的传输层 协议 (TCP或UDP)和使用的端口号 。Socket原意是 “插座”。通过将这3个参数结合起来,与一个“插座”Socket绑定,应用层 就可以和传输层 通过套接字接口,区分来自不同应用程序 进程或网络连接的通信,实现数据传输的并发服务。 Socket可以看成在两个程序进行通讯连接中的一个端点,是连接应用程序 和网络驱动程序 的桥梁,Socket在应用程序中创建,通过绑定与网络驱动建立关系。此后,应用程序 送给Socket的数据,由Socket交给网络驱动程序 向网络上发送出去。计算机从网络上收到与该Socket绑定IP地址和端口号 相关的数据后,由网络驱动程序 交给Socket,应用程序 便可从该Socket中提取接收到的数据,网络应用程序就是这样通过Socket进行数据的发送与接收的。
5 分类介绍
详细如图1: 我们来分析一下图1,Host A上的程序A将一段信息写入Socket中,Socket的内容被Host A的网络管理软件 访问,并将这段信息通过Host A的网络接口卡 发送到Host B,Host B的网络接口卡接收到这段信息后,传送给Host B的网络管理软件,网络管理软件将这段信息保存在Host B的Socket中,然后程序B才能在Socket中阅读这段信息。 假设在图1的网络中添加第三个主机Host C,那么Host A怎么知道信息被正确传送到Host B而不是被传送到Host C中了呢?基于TCP/IP网络中的每一个主机均被赋予了一个唯一的IP地址,IP地址是一个32位的无符号整数 ,由于没有转变成二进制,因此通常以小数点分隔,如:198.163.227.6,正如所见IP地址均由四个部分组成,每个部分的范围都是0-255,以表示8位地址。 值得注意的是IP地址都是32位地址,这是IP协议 版本4(简称Ipv4)规定的,目前由于IPv4地址已近耗尽,所以IPv6地址正逐渐代替Ipv4地址,Ipv6地址则是128位无符号整数 。 假设第二个程序被加入图1的网络的Host B中,那么由Host A传来的信息如何能被正确的传给程序B而不是传给新加入的程序呢?这是因为每一个基于TCP/IP网络通讯的程序都被赋予了唯一的端口和端口号 ,端口是一个信息缓冲区 ,用于保留Socket中的输入/输出信息,端口号是一个16位无符号整数,范围是0-65535,以区别主机上的每一个程序(端口号就像房屋中的房间号),低于256的端口号保留给标准应用程序 ,比如pop3的端口号就是110,每一个套接字都组合进了IP地址、端口、端口号,这样形成的整体就可以区别每一个套接字。
6 Sockets
流式套接字 本文描述流式套接字,它是两种可用的 Windows Sockets 类型中的一种。(另一种类型是数据文报套接字 。) 流式套接字提供没有记录边界的数据流:可以是双向的字节流 (应用程序 是全双工:可以通过套接字同时传输和接收)。可依赖流传递有序的、不重复的数据。(“有序”指数据包按发送顺序送达。“不重复”指一个特定的数据包只能获取一次。)这能确保收到流消息,而流非常适合处理大量数据。 网络传输层 可将数据拆分为分组或若干个大小适当的数据包。 CSocket 类将为您处理打包和解包 。 流基于显式连接:套接字 A 请求与套接字 B 建立连接;套接字 B 接受或拒绝此连接请求。 打电话的情况与流非常相似:正常情况下,接听方听到您的话和您讲话时的顺序一样,没有重复和遗漏。流套接字适合文件传输协议 (FTP) 这类实现,此协议有利于传输任意大小的 ASCII 或二进制文件 。 如果必须保证数据送达而且数据大小很大时,流式套接字优于数据文报套接字。有关流式套接字的更多信息,请参见 Windows Sockets 规范。该规范可在 Platform SDK 中获得。 MFC 示例 CHATTER 和 CHATSRVR 都使用流式套接字。这些示例可能已经设计为使用数据文报套接字向网络上的所有接收套接字广播。而目前的设计更好,这是因为: 广播模型受制于网络“洪水”(或“风暴”)问题。 后来采用的客户端 -服务器模型更有效。 流式模型提供可靠的数据传输,数据文报模型则未提供。 最终模型利用在 CArchive 类借给 CSocket 类的 Unicode 和 ANSI 套接字应用程序 之间通信的能力。
7 注意
: 如果使用 CSocket 类,则必须使用流。如果将套接字类型指定为 SOCK_DGRAM ,则 MFC 断言失败 Windows Sockets 示例列表 下列 MFC 示例程序阐释了 Windows Sockets 功能: CHATTER CHATTER 是一个 Windows 套接字客户端 示例应用程序 。它是一个具有拆分窗口的单文档界面 (SDI) 应用程序 ,允许用户将消息发送到讨论服务器 (CHATSRVR),讨论服务器然后将消息同时发送给其他多个 CHATTER 用户。 通过使 CHATTER 应用程序 向服务器发送广播数据文报包而不是消息流,可以在不使用客户端 /服务器模型的情况下编写 CHATTER 和 CHATSRVR。然而,与流式套接字不同,数据文报套接字不能保证一定会被传送;因此,一些消息可能不会到达讨论中的所有其他用户。
8 运行示例
生成并运行 CHATTER 示例 打开解决方案 chatter.sln。 在“生成”菜单 上单击“生成”。 在“调试”菜单 上单击“开始执行(不调试)”。 运行 CHATTER 时,有一个“Setup”对话框请求输入以下内容: Handle 用来寻址 所有消息的名称。例如,可以选择“”。发送的所有消息的前面都会自动加上名称“”。 Server 运行 CHATSVR 示例的计算机的 IP 地址。 Channel 标识要加入的讨论的数字(一台计算机可以运行多个讨论服务器)。 提供了所有这些信息并单击“OK”后,主应用程序 窗口随即出现。若要发送消息,请在下部窗格中键入消息。按 ENTER 键发送消息。若要发送多行消息,请按 CTRL+ENTER 键。关键字
9 示例
此示例说明了以下关键字 : AfxGetApp、AfxMessageBox、CArchive::Flush、CArchive::IsStoring、CControlBar::EnableDocking、CControlBar::GetBarStyle、CControlBar::SetBarStyle、CDialog::DoModal、CDocument::DeleteContents、CDocument::GetFirstViewPosition 、CDocument::GetNextView 、CDocument::OnNewDocument、CEditView::GetEditCtrl、CEditView::SerializeRaw、CFrameWnd::DockControlBar、CFrameWnd::EnableDocking、CFrameWnd::OnCreateClient、CFrameWnd::SetActiveView、CObject::AssertValid、CObject::Dump、CObject::IsKindOf、CObject::Serialize、CRect::Size、CSplitterWnd::CreateView、CSplitterWnd::GetPane、CStatusBar::Create、CStatusBar::SetIndicators 、CString::GetBuffer、CString::GetLength 、CString::IsEmpty、CString::LoadString、CString::ReleaseBuffer、CToolBar::Create、CToolBar::LoadBitmap、CToolBar::SetButtons 、CView::GetDocument、CView::OnDraw、CWinApp::AddDocTemplate 、CWinApp::InitInstance、CWinApp::LoadStdProfileSettings 、CWinApp::OnFileNew、CWnd::DestroyWindow、CWnd::DoDataExchange、CWnd::GetClientRect、CWnd::GetWindowText、CWnd::GetWindowTextLength 、CWnd::KillTimer 、CWnd::OnChar、CWnd::OnCreate、CWnd::OnTimer、CWnd::PreCreateWindow、CWnd::SetTimer、CWnd::SetWindowText、SetWindowText、rand、wsprintf 注意一些示例(如此示例)尚未经过修改以反映 Visual C++ 向导、库和编译器 的变化,但仍说明了如何完成所需的任务。 请参见 MFC 示例 CHATSRVR CHATSRVR 是 Windows 套接字服务器示例应用程序 ,它是一个单文档界面 (SDI) 应用程序,用于为 CHATTER 示例的客户端 实现讨论服务器。 通过使 CHATTER 应用程序向服务器发送广播数据文报包而不是消息流,可以在不使用客户端/服务器模型的情况下编写 CHATTER和 CHATSRVR。然而,与流式套接字不同,数据文报套接字不能保证一定会被传送;因此,一些消息可能不会到达讨论中的所有其他用户。生成并运行示例 生成并运行 CHATSRVR 示例 打开解决方案 chatsrvr.sln。 在“生成”菜单上单击“生成”。 在“调试”菜单上单击“开始执行(不调试)”。 运行 CHATSRVR 时会显示一个请求输入“Channel”的“Discussion”对话框。“Channel”是标识要支持的讨论的数字(一台计算机可以运行多个讨论服务器)。提供了此信息并单击“OK”后,主应用程序窗口随即出现。关键字
10 关键字
AfxMessageBox、CArchive::Flush、CArchive::IsStoring、CCmdUI::Enable、CCmdUI::SetText、CControlBar::EnableDocking、CControlBar::GetBarStyle、CControlBar::SetBarStyle、CDialog::DoModal、CDocument::DeleteContents、CDocument::OnNewDocument、CEditView::GetEditCtrl、CFrameWnd::DockControlBar、CFrameWnd::EnableDocking、CObject::AssertValid、CObject::Dump、CObject::Serialize、CStatusBar::Create、CStatusBar::SetIndicators、CString::GetBuffer、CString::LoadString、CString::ReleaseBuffer、CToolBar::Create、CToolBar::LoadBitmap、CToolBar::SetButtons、CView::GetDocument、CView::OnDraw、CWinApp::AddDocTemplate、CWinApp::ExitInstance、CWinApp::InitInstance、CWinApp::LoadStdProfileSettings、CWinApp::OnFileNew、CWnd::DoDataExchange、CWnd::GetWindowTextLength、CWnd::OnCreate、SetWindowText、wsprintf 注意 一些示例(如此示例)尚未经过修改以反映 Visual C++ 向导、库和编译器 的变化,但仍说明了如何完成所需的任务。
11 通信
要通过Internet进行通信,至少需要一对套接字,其中一个运行在客户端 ,称之为ClientSocket,另一个运行于服务器端面,称为ServerSocket。根据连接启动的方式以及本地要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听、客户端 请求、连接确认。 服务器监听是指服务端 套接字并不定位具体的客户端 套接字,而是处于等待连接的状态,实时监控网络状态。 客户端 请求是由客户端的套接字提出连接请求,要连接的目标是服务器端套接字。为此,客户端 的套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号 ,然后再向服务器端套接字提出连接请求。连接确认是当服务器端套接字监听到或者说接收到客户端 套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的信息发送给客户端,一旦客户端确认了此连接,连接即可建立。而服务器端继续处于监听状态 ,继续接收其他客户端 的连接请求。 使用套接字进行数据处理有两种基本模式:同步和异步。 同步模式: 同步模式的特点是在通过Socket进行连接、接收、发送数据时,客户机和服务器在接收到对方响应前会处于阻塞状态,即一直等到收到对方请求进才继续执行下面的语句。可见,同步模式只适用于数据处理不太多的场合。当程序执行的任务很多时,长时间的等待可能会让用户无法忍受。 异步模式: 异步模式的特点是在通过Socket进行连接、接收、发送操作时,客户机或服务器不会处于阻塞方式,而是利用callback机制进行连接、接收、发送处理,这样就可以在调用发送或接收的方法后直接返回,并继续执行下面的程序。可见,异步套接字特别适用于进行大量数据处理 的场合。 使用同步套接字进行编程比较简单,而异步套接字编程则比较复杂。