揭开Socket编程的面纱.docx_第1页
揭开Socket编程的面纱.docx_第2页
揭开Socket编程的面纱.docx_第3页
揭开Socket编程的面纱.docx_第4页
揭开Socket编程的面纱.docx_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

揭开Socket编程的面纱对 TCP/IP 、 UDP 、 Socket 编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问:1. 什么是 TCP/IP、UDP?2. Socket在哪里呢?3. Socket是什么呢?4. 你会使用它们吗?什么是TCP/IP、UDP?TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。这里有一张图,表明了这些协议的关系。图1TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。Socket在哪里呢?在图1中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。图2原来Socket在这里。Socket是什么呢?Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。你会使用它们吗?前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。图3先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。在这里我就举个简单的例子,我们走的是TCP协议这条路(见图2)。例子用MFC编写,运行的界面如下:图4图5在客户端输入服务器端的IP地址和发送的数据,然后按发送按钮,服务器端接收到数据,然后回应客户端。客户端读取回应的数据,显示在界面上。下面是接收数据和发送数据的函数:int Receive(SOCKET fd, char *szText, int len)int cnt;int rc;cnt = len;while (cnt 0) rc = recv(fd, szText, cnt, 0);if (rc = SOCKET_ERROR) return- 1; if (rc = 0)return len - cnt;szText += rc;cnt -= rc; return len;int Send(SOCKET fd, char *szText, int len)int cnt;int rc;cnt = len;while (cnt 0) rc = send(fd, szText, cnt, 0);if (rc = SOCKET_ERROR) return- 1; if (rc = 0)return len - cnt;szText += rc;cnt -= rc; return len;服务器端:在服务器端,主要是启动Socket和监听线程。#define DEFAULT_PORT 2000void CServerDlg:OnStart()sockaddr_in local;DWORD dwThreadID = 0;local.sin_family = AF_INET;/设置的端口为DEFAULT_PORT。local.sin_port = htons(DEFAULT_PORT);/IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。local.sin_addr.S_un.S_addr = INADDR_ANY;/初始化Socketm_Listening = socket(AF_INET, SOCK_STREAM, 0);if (m_Listening = INVALID_SOCKET) return ; /将本地地址绑定到所创建的套接字上if (bind(m_Listening, (LPSOCKADDR) &local, sizeof(local) = SOCKET_ERROR) closesocket(m_Listening);return ; /创建监听线程,这样也能响应界面上操作。m_hListenThread = :CreateThread(NULL, 0, ListenThread, this, 0, &dwThreadID);m_StartBtn.EnableWindow(FALSE);m_StopBtn.EnableWindow(TRUE);/监听线程函数:WORD WINAPI CServerDlg:ListenThread(LPVOID lpparam)CServerDlg *pDlg = (CServerDlg*)lpparam;if (pDlg = NULL)return 0;SOCKET Listening = pDlg-m_Listening;/开始监听是否有客户端连接。if (listen(Listening, 40) = SOCKET_ERROR) return 0; char szBufMAX_PATH;/初始化memset(szBuf, 0, MAX_PATH);while (1) SOCKET ConnectSocket;sockaddr_in ClientAddr;int nLen = sizeof(sockaddr);/阻塞直到有客户端连接,不然多浪费CPU资源。ConnectSocket = accept(Listening, (sockaddr*) &ClientAddr, &nLen);/都到客户端的IP地址。char *pAddrname = inet_ntoa(ClientAddr.sin_addr);pDlg-Receive(ConnectSocket, szBuf, 100);/界面上显示请求数据。pDlg-SetRequestText(szBuf);strcat(szBuf, :我是老猫,收到();strcat(szBuf, pAddrname);strcat(szBuf, ));/向客户端发送回应数据pDlg-Send(ConnectSocket, szBuf, 100); return 0;服务器端一直在监听是否有客户端连接,如有连接,处理客户端的请求,给出回应,然后继续监听。客户端:客户端的发送函数:#define DEFAULT_PORT 2000void CClientDlg:OnSend()DWORD dwIP = 0;TCHAR szTextMAX_PATH;memset(szText, 0, MAX_PATH);m_IP.GetWindowText(szText, MAX_PATH);/把字符串形式的IP地址转成IN_ADDR结构需要的形式。dwIP = inet_addr(szText);m_RequestEdit.GetWindowText(szText, MAX_PATH);ockaddr_in local;SOCKET socketTmp;/必须是AF_INET,表示该socket在Internet域中进行通信local.sin_family = AF_INET;/端口号local.sin_port = htons(DEFAULT_PORT);/服务器的IP地址。local.sin_addr.S_un.S_addr = dwIP;/初始化SocketsocketTmp = socket(AF_INET, SOCK_STREAM, 0);/连接服务器if (connect(socketTmp, (LPSOCKADDR) &local, sizeof(local) 0) closesocket(socketTmp);MessageBox(连接服务器失败。);return ; /发送请求,为简单只发100字节,在服务器端也规定100字节。Send(socketTmp, szText, 100);/读取服务器端返回的数据。memset(szText, 0, MAX_PATH);/接收服务器端的回应。Receive(socketTmp, szText, 100);CHAR szMessageMAX_PATH;memset(szMessage, 0, MAX_PATH);strcat(szMessage, szText);/界面上显示回应数据。m_ReplyBtn.SetWindowText(szMessage);closesocket(socketTmp);客户端就一个函数完成了一次通信。在这里IP地址为何用127.0.0.1呢?使用这个IP地址,服务器端和客户端就能运行在同一台机器上,这样调试方便多了。当然你可以在你朋友的机器上运行Server程序(本人在局域网中测试过),在自己的机器上运行Client程序,当然输入的IP地址就该是你朋友机器的IP地址了。简单的理论和实践都说了,现在Socket编程不神秘了吧?希望对你有些帮助。=以下是作者和读者的舌战,讨论的是套接字到底是什么东西,讨论来讨论去貌似没一个统一的意见re:BSD Socket是一个网络编程的API接口,它并非仅仅针对IP协议的。把Socket放到TCP/UDP的协议上层似乎不是太妥当?re:其实socket也没有层的概念,在文章中我说过,它其实是一个facade设计模式的应用,让编程变的更简单。是一个软件抽象层。在网络编程中,我们大量用的都是通过socket实现的。re:将socket理解为tcp/udp的facade的确不够恰当。第一,socket并不是以面向对象的方式提供的,在这里引用面向对象和设计模式的术语失妥。第二,socket事实上并不是留给编程开发的,而是留给网络操作系统实现协议栈的一个支持模型。例如berkeley socket和windows socket。至于编程开发时使用的socket模型和相应的API,则是操作系统服务API。事实上socket也不是tcp/udp服务的全部而是部分。不过文章归纳得还不错,只是没有提到tcp/udp中端口的概念是一大遗憾。如果用电话来对应网络会话的话,端口应该正好比分机号。re:其实对于facade设计模式,我的理解是不能局限于面向对象。facade定义是把很多复杂的东西放在后面,客户只需通过简单的接口,而不需要知道下面复杂的逻辑等。当然由于我对socket还没有能达到很高的境界,所以还有很多不知的。我自己也正在学习,比如在socket编程中,select函数还是有很重要的地位的,等自己正在明白了,还会有下篇的介绍。re:楼主不够谦虚!楼主可能为自己“创造性地”将socket理解为tcp/ip的facade偷偷高兴呢,其实极其错误!tcp/ip仅仅是一套协议、规范,并没有实体存在,是完全抽象的;socket模型则是清晰而具体的。而大部分情况下,门面模型是可有可无的,只是为了满足封装一个简单的外部门面而存在的,而你根本没有绕开socket去直接操纵tcp/ip的可能。换句话说,tcp/ip和socket并没有相提并论的前提,根本是为了解决同一个问题的两个步骤,是完全分离的。re:我想这不是谦虚不谦虚的问题,有问题就可以争论,你说呢?有一点我想你说错了,牛人是可以绕过socket去直接操纵tcp/ip的,只要他对tcp/ip协议很了解。就说好的抓包程序,单用socket是无法实现的。to 航天奇侠:是用SmartDraw软件作的图。re:关系是不是搞反了哟。tcp/ip应该是建立在socket的基础之上的,绕过socket去操作tcp/ip,还是第一次听到这样说。re:我们平时说的TCP/IP其实是一组协议,而不是一个叫TCP/IP的协议,它包括运输层,网络层,链路层。我们经常用的是TCP和UDP。re:我晕.抓包程序 基本上是使用raw socket(原始套接字)实现的,这是socket的高级功能,并不是因为对tcp/ip协议很了解,而是对socket很了解(当然不了解tcp/ip也无法理解高级的socket)。离开特定操作系统(或者虚拟机)讨论tcp/ip的编程是没有意义的。yf2008:没有tcp/ip建立在socket之上或者socket建立在tcp/ip之上这样的说法,都有自己的独立的完整体系,其功能也完全不同。re:raw socket其实就是跳过TCP,UDP这一层。用socket我们不光是只发数据了,还要TCP和UDP的头。为何不能跳过socket呢?我个人觉得可以。跳过它,都自己干。当然这要很大的勇气和足够的知识。呵呵。我看socket编程还是有很多讨论的地方的吗?欢迎多加讨论,这样我们就能搞清楚它了。共同进步是我们的目标。shootingstarre:呵呵,越讨论越乱了 *_*谈谈我的看法:ip仅仅是一个协议,大家按照这个协议规范来发送和解析这个某个流。大家可以自己一个字节一个字节来构建自己的IP数据报文,并非一定需要通过socket接口。(通过流行的winpcap,你可以抛开socket,发送自己构建的任意的IP报文)socket是一个大家都认为好用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论