| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> TCP与UDP之Socket编程 -> 正文阅读 |
|
[网络协议]TCP与UDP之Socket编程 |
本文主要讲的是如何用Socket实现TCP和UDP基础上的服务器端和客户端通信。在代码上的通信流程和一些细节以及两者在代码上的区别和原因。 目录 一、Socket首先明确,Socket是一个本地的标识,只和本端有关系,其它端是不知道的。 同时Socket标识着本地ip的某个端口和其它端ip的某个端口的一个连接关系,因此这个socket里面有自己的ip和端口。 它就像本端的某一扇门一样,一扇标识的门,我们需要将我们的想要发送的数据从这扇门发出去,同时向本机端口发送的数据也需要通过这扇门收进来。这个是socket最主要的作用,就是收和发的作用,数据发出和接收都需要通过这个socket。当我们需要发出相关数据时,需要调用这个socket发出的相关方法。当我们需要接收数据时,我们也是需要调用这个socket的相关方法来接收的。 并且注意了socket标识的作用,就是当我们发消息给对方的时候,对方知道是我们发的,就是因为我们是通过这个socket发的,因为socket上面有端口号和ip地址。接也是同样道理的,网络这么大,怎么知道是哪个ip地址哪个端口来接呢?就是因为有socket在这里,当有消息发过来的时候,socket可以和发过来的消息对应上,然后通过对应的上的这个socket来接收消息。<---这里主要是udp的,但其实tcp也是一样的,只是没有特别显式而已。 简写步骤 注意这里都是一次性的操作,也就是一个客户端发过去然后收回来,没有实现同一个客户端向服务器多次发送的操作。tcp代码在SocketTest003 二、TCP方式通信服务器端● 创建欢迎套接字socket1、创建欢迎套接字socket,其中需要传入ip地址和端口号,也就是握手的操作。注意这个socket只是一个本地的标识,是等着客户端来连接的。 ●?创建专属套接字socket?2、需要在欢迎套接字的基础调用accept方法,为发送端和自己创建一个专门的套接字socket,不需要传入ip地址和端口号了。然后利用这个专属socket来进行读取和发送的操作。 ●?读取数据流3、需要调用socket的getInputStream方法,然后就可以调用read方法就可以读取到客户端发送过来的数据了。这里我们使用了缓冲流BufferedReader来读取。然后记得最后需要关闭这个缓冲流,但是不能直接close,而是要调用shutdownInput()方法,这样只会关闭这个读的部分而不会直接关闭socket,而close会。然后需要注意,read的时候如果没有数据发过来,是会阻塞的。 ●?发送数据流4、需要调用socket的getOutputStream方法,然后调用write方法就可以往外面写出,数据就写出去了,对方如果有调用read方法就接收的到了。这里我们使用了缓冲流BufferedWriter来写出。然后切记要调用一下flush方法将缓存里面的东西刷出去。最后记得需要关闭这个流,但是也不能直接close,而是要调用shutdownOutput()方法,这样只会关闭输出的部分而不会关闭socket。 ●?关闭socket直接调用socket的close方法将它们关闭。 客户端●?创建socket创建一个本地标识socket,里面传入ip地址和端口号port。然后就可以利用这个socket进行收数据流和发数据流的工作了。 ●?发数据流调用socket的getOutputStream()方法获取到输出流,然后调用write方法将数据写出去,然后还有很重要的一步就是需要这个输出流关闭掉才能算是真正写出去!但是注意这里不能直接调用writer的close方法,因为这样会直接把socket关闭掉,导致后面的用不了了。而是要先用flush,将缓冲区里面的刷出去,然后调用shutdownOutput()方法将输出流关闭,这样数据才算真正发出去了。 此处疑问:为什么一定要关闭输出流,数据才能发出去啊!? ●?收数据流调用socket的getInputStream()方法获取输入流,然后调用read方法将数据读进来。最后调用shutdownInputStream()方法将输入流关闭。 ●?关闭socket最后调用socket的close方法将socket关闭掉。 三、UDP方式通信服务器端●?创建socket1、首先创建一个socket作为本地的标识,这个socket里面有端口号,有ip地址(操作系统会帮忙赋值)。利用这个socket发出去的packet就会带有这个socket的信息也就是InetAddress和port。 ●?接收数据报2、然后事先准备好一个packet用于接收消息。 3、然后调用socket的receive方法,将packet传进去,packet就有数据了。packet里面有对方发送过来的数据,还有对方的ip地址和相应的端口号。 ●?发送数据报4、准备一个socket,在这个socket里面放置要发送的数据,要发送的地址,包括对方ip及其端口号。 ●?关闭socket5、最后关闭socket就行了 客户端●?创建socket1、创建一个属于客户端的socket,里面有端口号和ip地址,所有的收和发都是需要经过这个socket的。这里需要专门指定ip是因为和服务器区别,服务器那里是直接用系统的,而这里是指定的,所以两者不一样。 ●?发送数据报2、和上面发送数据包一样,创建packet,然后packet里面要有数据,对方端口号和对方ip地址。 3、然后调用send方法将packet传进去 ●?接收数据报4、也是和上面一样,需要预先准备好一个packet,然后调用receive方法 ●?关闭socket5、最后关闭socket 四、UDP和TCP的区别1、TCP是面向连接的,UDP是无连接的,其实也就是要不要事先握手。这就造成TCP连接需要先创建一个“欢迎Socket”。而UDP是不用的。也就是TCP连接需要额外建立一个serverSocket。 2、建立在TCP上的连接,需要专门创建专属的socket来标志服务器端和客户端的连接关系。而UDP是不需要的。TCP需要在serverSocket的基础上建立一个专属的连接。Socket socket = serverSocket.accept( ); 3、TCP发送和接收消息,发的和接的是数据流。而UDP发送和接收消息,发的和接的是数据报。流和报的区别需要找篇文章深究一下。而流Stream则需要利用socket来拿到流和发出流,xxx.read( )读进来和xxx.write( )写出去。并且有关闭流的操作,xxx.shutdownInput ( )和xxx.shutdownOutput( )。而报packet就是直接发和收的,socket.send(packet)和socket.receive( packet)。 4、向外发送时是否需要设置端口号和ip地址的区别: ????????4.1 使用TCP时是不用的,因为在创建“欢迎连接”的时候已经设置好了和服务器端连接的信息,然后又在accept那里设置好客户端连接的信息了。因此在发送流的时候无需再专门设置要发向哪里。 ? ? ? ? 4.2 而再使用UDP时需要,从图像上面理解就是一去然后就没有了。就是这个消息我发过去,然后就没有了。因此发送数据报的时候,需要在packet那里标注好发往哪里,ip地址和端口号。而相反,TCP就是不用的,从图像上面看就是建立了一个连接,然后可以在这个欢迎连接的基础上的专属连接上面一直发来发去的,不需要指定某个位置。 ?写的乱七八糟的,还是保留下来或许有用呢? ?三、UDP 2.1 UDP简介 相比于TCP的面向连接,UDP是无连接的,无连接其实指的就是两个端(在这里就是客户端和服务端)在建立连接之前不需要进行挥手,直接进行连接,因此这个UDP也是不可靠的连接。并且UDP因为是无连接的,所以不需要像TCP连接那样,专门建立一个socket连接来进行握手先。UDP直接就是客户端和服务器端进行连接了。 因此就是服务器端直接创建一个socket,然后这个socket就是守护在这个服务器端的某个端口上面等待客户端的请求,也就是利用这个服务器端的一个socket,就可以完成和所有客户端的连接,利用这个socket来进行对所有请求的收和发的工作。 2.2? 流程 本章节代码在socket_udp_001里面 服务器端 第一步?这里先编写服务器端的代码,首先服务器端需要创建一个socket,其中这个socket需要传入一个port 端口号参数,这样这个socket代表的就是这个主机中这个端口号的门,用于收和发与这个主机上这个端口号上的工作。发出去的数据报需要通过这个socket,收进来的socket也需要通过这个socket。
第二步?准备收的工作,也就是客户端向这个服务器的这个端口发送消息,这个socket将它们收进来,利用预先准备的数据包来存数据。 因为UDP是数据包的发送和接收方式,所以这里需要先准备一个数据包来接收。然后将这个数据包放进receive方法里面,当有数据发送过来的时候就将收到的数据放在这个数据包的缓存上面,然后我们预先准备的这个数据包里面就有数据了,然后我们就可以读里面的数据了。(因为是缓存的是byte字节,所以我们需要转化为String)。 并且注意,发送过来的数据还包括了发送端的ip地址和端口号,因此这个数据包里面还包括了发送端的ip地址及其端口号。 然后还需要注意,这个receive方法是用来接数据报的,那么也就是说如果没有数据发送过来,那么这个receive方法就会一直处于待命状态,会阻塞住,直到有数据发过来的时候才会执行完这行代码。
第三步?第三步就是服务器端向客户端发送消息了。同理,基于UDP就是用数据报packet的方式来收和发的,因此自然这里发消息也是需要用到数据包packet的。但是注意这里的构造数据包的传入参数和上面构造数据包的方式是不一样的,所以两者的作用也是不一样的,一个是收一个是发。 这里就是需要准备一个数据包,放置四个东西:对方ip地址,对方端口号,发送的内容,数据包的长度。然后调用socket的send方法将这个数据包发送出去。
第四步?第四步就是非常常规的一步了,为了安全起见,需要关闭socket。当然一般因为我们是要让这个服务器的这个socket一直等待请求的,所以不需要直接关闭,除非不想让它请求了。 完整代码 以下是完整代码,这里和上面的变化就是加入了线程和一个while循环。线程是因为这是一个网络操作,肯定是需要联网的,所以需要开一个线程来专门处理这些东西。然后因为我们需要让这个这个服务器socket端口建立起来之后就一直处于待命状态以便不用反复开,因此就是利用一个while循环,每当处理完一个请求响应和发送之后就进行下一次等待循环响应之中。
????????????????????????????????????????????????????????????????????????客户端 客户端其实和服务器端差不多,只不过客户端是先发然后再收的。原理也是一样,需要创建一个socket本地标识,利用这个socket来收和发。注意也是一样,发出去的时候利用packet包来发,收的时候利用packet来收。 因为socket中带有自己的ip地址和端口号,因此利用这个socket来发时,包里面其实就自动携带了ip地址和端口号了。然后收也是一样的,因为有ip地址和端口号来标识,所以当别人发过来的时候能够对应上。 完整代码如下:
|
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 2:02:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |