tcp和udp向应用层提供了使用的接口,而对他们的使用可以使用套接字Socket来进行操作
因为有俩种协议,所以也会有俩套对应的套接字
UDP DatagramSocket 类
建立一个UDP回响服务器
创建一个socket对象,对数据的操作都要是用这个类,在创建时可以指定端口号,表示这个程序将会运行在你指定的端口号中,如果没有指定端口号,那他默认是0
使用receive()方法来接受发送给这个程序的数据,接收到的数据会储存在DatagramPacket这个对象中,如果DatagramPacket在接收大于你自己设置的大小的最大值的话,那他会将数据截断,只会读到自己能读的最大值,而多余的会丢弃,并不会扩容
现在得到了这个数据,那读出其中的有效数据还需要进行进一步的处理
在得到了数据之后就可以进行对应的业务操作了,这里我是直接返回这个数据
在的到返回的数据在对这个数据进行包装,然后发送回去,要将数据发送回去,就需要知道发送端的ip地址,端口号,这俩个数据都储存在最开始收到数据的packet类中
服务器的启动
这样一次请求的接收和返回响应的过程就写完了,不过只是这样写的话,他处理一次请求就会结束了,所以需要在外面套一个while(true)死循环来接收请求,还有这个服务器程序是运行在自己的电脑上的,我们是用127.0.0.1 这个IP地址来表示自己的主机,具体点来说这个程序是运行在ip地址为127.0.0.1,端口号为8888中
客户端的实现 和服务端的实现很相似
初始化
这里的ip和port都是对应服务器的位置
请求的发送
接收服务器的响应
启动客户端
这就是一个简单的udp协议的服务器的实现,那为什么能够实现请求的发送和放回的呢?
可以这样理解,ip地址就对应的是浙海大的二食堂,而端口号就是其中的一个快餐档口,这样当我想吃快餐时,可以先走到海大的二食堂,让后在往里面走,找到快餐档口,这个快餐档口对应的是我这里运行的udp服务器,而我就是服务端
不过要注意的是,现在的程序并没有部署到网络上去他在网络上是没有位置(ip)的,所以是能在自己的电脑上才能正常使用,而我在这里写的127.0.0.1这是只是在我这个主机这个层面上的ip地址
TCP Socket
TCP是有连接的协议,那么对于连接的建立也许要一个对应的类来进行,这个类是ServerSocket,当ServerSocket建立好了连接,就可以使用Socket获取这个连接对他进行操作
获取连接,serverSocket储存了建立好的连接,是用InputStream和OutputStream来对着连接进行操作,具体的操作就将数据从对应的接受和发送缓冲区中读出和写入并发送
读取数据read
读到了数据之后就根据这些数据来完成对应的操作,这里我直接返回了
将读到的数据写入缓冲区,但并不代表发送了,因为缓冲区会等数据积累到一定的量之后才会发送,使用flush方法强制将数据从缓冲区中写入到网卡中并发送出去
这样就完成了一次数据的接收和发送,但因为会有多次的数据的交换,那么就在这外面套一层死循环
还有建立的连接也不会做一个所以在连接的建立上也在一层循环这样就可以处理多个不同的连接的请求了
但还有问题,在对方断开连接之后,会直接抛出异常,被catch捕捉之后,还是会抛出异常,这样就会是的程序终止,这是绝对不行的,因为对方的断开导致我服务直接崩溃了,所以我要单独在数据的读取这里再捕捉异常,但对方断开之后会读不了数据然后抛出IOException异常
当在外层只是通过通过while循环来线性的处理连接请求的话效率太低了,于是我们可以使用多线程来对每个联机创建一个线程
ExecutorService他内置初始话好了的线程池,使用简单
将对连接的操作放到了mainlogic中去了
现在就可以同时对多个连接进行操作了,别忘了将连接关闭
现在来实现客户端
使用socket来和服务器建立连接
数据的发送和服务器的实现一样
有所不同的是我在这里对 out 和in套了层壳这样使用起来更加的方便
将流的获取放到了try()里面,这样在出了try中他会自动的关闭连接,不用我们自己写了
启动程序
现在就能使用了
现在一个基于tcp和udp的服务器和客户端就粗略的实现成功了。
end yeyye