揭开Socket编程的面纱
对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问:
什么是TCP/IP、UDP?
Socket在哪里呢?
Socket是什么呢?
你会使用它们吗?
什么是TCP/IP、UDP?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。这里有一张图,表明了这些协议的关系。
图1
TCP/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);}
监听线程函数:
DWORD 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 szBuf[MAX_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 szText[MAX_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);sockaddr_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);TCHAR szMessage[MAX_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编程不神秘了吧?希望对你有些帮助。
转载于:https://www.cnblogs.com/Solomon-xm/p/9446770.html
揭开Socket编程的面纱相关推荐
- Raw Socket和Socket编程
1.原始套接字(raw socket) 1.1 原始套接字工作原理与规则 原始套接字是一个特殊的套接字类型,它的创建方式跟TCP/UDP创建方法几乎是 一摸一样,例如,通过 CODE ...
- Java Socket编程----通信是这样炼成的
转载自 Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socke ...
- Linux调试私房菜(四)揭开链接器的面纱、汇编语言的内嵌编程
七.揭开链接器的面纱(上) 1. 问题 源文件被编译后生成目标文件,这些目标文件如何生存最终的可执行程序? 2. 链接器的意义 链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能 ...
- 揭开木马的神秘面纱 2
揭开木马的神秘面纱zz 2 离冰河二的问世已经快一年了,大家对于木马这种远程控制软件也有了一定的认 识,比如:他会改注册表,他会监听端口等等,和一年前几乎没有人懂得木马是什么东 西相比,这是一个质 ...
- 了解黑客的关键工具---揭开Shellcode的神秘面纱
2019独角兽企业重金招聘Python工程师标准>>> ref: http://zhaisj.blog.51cto.com/219066/61428/ 了解黑客的关键工具---揭开 ...
- 未来已来?揭开量子计算机的神秘面纱
从第一台现代计算机ENIAC的诞生到个人PC时代的降临,从互联网概念的提出到移动互联的疾跑,在这个信息年代里,变革正以前所未有的速度改变着我们熟悉的世界.熟悉的生活. 作为个人,我们早已习惯于智能计算 ...
- 【翻译】揭开HTML5的神秘面纱
写在前面的话: 这篇文章摘自Mozilla官网,主要针对HTML5和本地应用发表了一些.没有设计到技术,所以基本是逐字翻译,但愿我蹩脚的英语水平能把大师的 Chris Heilmann的思想整理明白. ...
- 揭开 LVS 神秘的面纱
文章目录 揭开 LVS 神秘的面纱 一 前言 二 认识 LVS 三 了解三种模式 3.1 Virtual Server via Network Address Translation(VS/NAT) ...
- 揭开木马的神秘面纱 1
揭开木马的神秘面纱 1 前言 在网上,大家最关心的事情之一就是木马:最近出了新的木马吗?木马究竟能实现 哪些功能?木马如何防治?木马究竟是如何工作的?本文试图以我国最著名的木马之 - 冰河为例,向大 ...
最新文章
- dba的前景_运维、测试、程序员,这些技术岗位哪个更有前景?
- 机试指南第二章-经典入门-查找例题自解
- 程序员不满薪资拒绝offer,HR怒称:估计你一辈子就是个程序员了!
- python高手养成_Python用PyQt5制作颜色对话框,PyQt图形界面编程之QColorDialog
- 编译原理 编译器自动生成工具
- 玩客云pc端_玩客云下载-玩客云电脑版下载-华军软件园
- 算法竞赛入门经典(第2版)—索引
- 液压系统仿真软件_利用仿真软件判断系统稳定
- 大数据相关面试题整理-带答案
- 群英传内推第001期
- 百度404.html,百度标准死链(404页面)官方文档全解析
- c语言编程运动会分数统计系统,东华大学数据结构设计C语言运动会分数统计系统...
- 小武学fpgastep4
- 北京市211学校计算机专业,北京较容易考的2所211大学,王牌专业实力强悍,学生不愁就业...
- 不入耳式蓝牙耳机什么牌子好、最好的骨传导耳机推荐
- 【BZOJ 2243】染色
- 云南省二级c计算机考试试题,2014云南省计算机等级考试试题 二级C试题最新考试试题库(完整版)...
- 跟益达学Solr5之使用MMSeg4J分词器
- android下雨动画效果,Android 自定义View(二) 下雨效果
- Win10 1803 (17134)找回控制面板语言设定的方法
热门文章
- windows server 2008 - 创建域和本机用户
- XE3随笔6:SuperObject 的 JSON 对象中还可以包含 方法
- C-二维数组,多维数组
- 对于表列数据类型选择的一点思考
- 配置GoldenGate源端Manager参数
- Ubuntu 11.10 开机让 Varnish 跟随 Nginx 一起启动
- 创建一个属于自己的名称空间.
- JAVA调用R语言之Rserve
- asp.net html 加密解密,三种方法还原ASP.NET可逆加密内容
- android ios 上传图片到服务器,.net 接收ios, android的上传图片