做外贸营销网站,如何制作一个二维码,wordpress重装教程视频,windows设置wordpress系列文章目录
1、 初识网络 网络编程套接字 系列文章目录前言一、TCP和UDP协议的引入二、UDP网络编程1.Java中的UDP2.UDP回显代码案例3.UDP网络编程的注意事项 三、TCP网络编程1.TCP回显代码案例2.TCP多线程使用 总结 前言
在学习完基础的网络知识后#xff0c;完成跨主机通…系列文章目录
1、 初识网络 网络编程套接字 系列文章目录前言一、TCP和UDP协议的引入二、UDP网络编程1.Java中的UDP2.UDP回显代码案例3.UDP网络编程的注意事项 三、TCP网络编程1.TCP回显代码案例2.TCP多线程使用 总结 前言
在学习完基础的网络知识后完成跨主机通信的网络编程。 一、TCP和UDP协议的引入
注意TCP协议并非TCP/IP模型。 TCP和UDP都属于传输层协议中的一种为应用层提供服务。但是二者之间的特点和差异都很大因此有了两套API分别应用于二者。 特点 TCP:有连接可靠传输面向字节流全双工 UDP无连接、不可靠传输、面向数据报、全双工
其中有连接的意思是如同打电话一样在电话接通以后才能相互通信无连接就像发送短信不需要“先接通”允许直接发送。 可靠传输的意思是将要传输的数据尽可能传输给对方不可靠传输的意思是在数据传输时不关心对方是否收到信息。 面向字节流和文件操作中的字节流类似读写操作十分灵活。 面向数据报在UDP协议中传输数据的基本单位时一个个UDP数据报一次读写只能读写一个完整的UDP数据报。 全双工在一条链路中能够进行双向通信半双工一条链路中只能进行单向通信。
二、UDP网络编程
1.Java中的UDP
在Java中引入系统的API(称为Socket API)并进行封装在Java中主要有两个类DatagramSocket和DatagramPacket。 1DatagramSocketsocke可以理解为是一种文件socket文件可以视为对网卡的硬件设备进行的抽象化。在UDP中对于操作系统中socket概念的封装针对该对象进行读写操作也可以理解为对网卡硬件设备的操作。 2DatagramPacket: 针对UDP数据报的一个抽象表示一个DatagramPacket对象就相当于一个UDP数据报。一次发送/接收就相当于传输了一个DatagramPacket对象。
2.UDP回显代码案例
所谓回显代码即客户端请求什么内容服务器就返回什么代码。回显代码中没有实现复杂的逻辑能够最简单的反映UDP的服务器和客户端之间的互动情况。
UDPEchoServer:在Server端端口号是固定的DaragramSocket 在构造方法中传入端口号。在服务器启动之后需要不断接收请求和返回请求值。 在DatagramSocket中的receive方法负责接收客户端发送过来的请求 将接收到的数据转换成字符串request作为后面处理请求的参数。通过方法process运行之后返回的结果需要数据报进行封装因此在结果返回之后新建一个数据报对象并将字符串结果转换成字节流。通过socket.send方法发送。
public class UdpEchoServer {DatagramSocket socket null;public UdpEchoServer(int port) throws SocketException {socket new DatagramSocket(port);}public void start() throws IOException {System.out.println(服务器启动);while (true) {DatagramPacket requestPacket new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);String request new String(requestPacket.getData(),0,requestPacket.getLength());String response this.process(request);DatagramPacket responsePacket new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf([%s:%d] req %s,res %s \n,requestPacket.getAddress(),requestPacket.getPort(),request,response);}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server new UdpEchoServer(9090);server.start();}
}UDPEchoClient:在客户端用户发起请求并接收返回的结果。对服务器发送的信息应该包括用户IP地址、用户端口号的信息。通过DatagramSocket类中的send方法发送请求。 在start()方法中新建字符串request来保存用户所发送的请求由于网卡的的性质需要发送数据报格式。为了解决这个问题我们需要new一个数据报requestPacket对请求内容进行封装。同时我们需要把字符串的数据转换成字节流的数据。 INetAddress中的getByName方法中存储着服务器的IP地址以及服务器的端口号。 在发送请求之后等待数据接收状态下receive()方法进入阻塞状态。 在接收到数据之后将字节流数据转换成字符串的形式用response接收。
public class UdpEchoClient {private DatagramSocket socket null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.socket new DatagramSocket();this.serverIp serverIp;this.serverPort serverPort;}public void start() throws IOException {System.out.println(客户端启动);Scanner scanner new Scanner(System.in);while (true) {System.out.println(请输入要发送的请求);String request scanner.next();DatagramPacket requestPacket new DatagramPacket(request.getBytes(),0,request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);DatagramPacket responsePacket new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response new String(responsePacket.getData(),0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client new UdpEchoClient(127.0.0.1,9090);client.start();}
}
最终我们成功完成了UDP中基础的数据请求与通信。 3.UDP网络编程的注意事项
在上面的UDP编程中主要可以分为以下几个步骤如下图所示 进程的运行顺序是先启动服务器再启动客户端。在代码编写过程中都没有涉及到close操作的原因DatagreamSocket作为这个进程的对象和服务器程序的生命周期是一样的。如果在某个程序中socket对象的生命周期和进程不一样需要提前释放的话就需要进行close操作。
三、TCP网络编程
在TCP中的socket api中与UDP不同的是在TCP中ServerSocket类是专门给服务器使用的。 Socket类是专门作用于客户端和服务器之间进行通信使用的。 由于TCP属于有连接和可靠传输他们之间必须时刻保持通信状态。在ServerSocket中有accept方法接收客户端发来的请求。
1.TCP回显代码案例
我们知道TCP是面向字节流的因此在TCP中的操作是以流对象进行操作的。
在Socket类中通过两个方法getInputStream和getOutpurStream 进行操作的。在服务器中start方法中通过accept同意客户端连接。接下来调用processConnection使用Scanner读取InputStream流中的数据内容。使用Scanner的好处是对于客户端传输进来的字节流Scanner会自动将这些数据转换成String。在方法start中循环保持与客户端之间的通信。通过scanner.hasNext()方法判断是否还有输入当客户端关闭了连接之后服务器的输入流会收到一个EOF信号从而判断出没有输入了最终结束循环。将回显的结果以response的结果以二进制的形式写入outputStream中。最后处理完client的请求之后客户端下线之后回收client对象当下次重新有新的客户端时重新启用。
public void start() throws IOException {System.out.println(服务器启动);//accept可以阻塞等待Socket socketClient serverSocket.accept();processConnection(socketClient);}private void processConnection(Socket socketClient) throws IOException {System.out.printf([%s:%d] 客户端上线\n, socketClient.getInetAddress(),socketClient.getPort());try(InputStream inputStream socketClient.getInputStream();OutputStream outputStream socketClient.getOutputStream()) {Scanner scanner new Scanner(inputStream);while (true) {if (!scanner.hasNext()) {System.out.printf([%s:%d] 客户端下线\n, socketClient.getInetAddress(),socketClient.getPort());break;}//接收客户端发送过来的请求String request scanner.next();//处理请求String response process(request);//把响应写回客户端outputStream.write(response.getBytes(),0,response.getBytes().length);//服务器打印日志System.out.printf([%s:%d] req %s resp %s,socketClient.getInetAddress(),socketClient.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {socketClient.close();}}在客户端方面通过scannerNetWork读取inputStream中的数据。将请求的内容以二进制的形式写入outputStream中。当服务器关闭后scannerNetWork传入服务器的EOF信号代表着双方连接中断因此可以退出循环结束进程。
public void start() {System.out.println(客户端启动);Scanner scanner new Scanner(System.in);try(InputStream inputStream clientSocket.getInputStream();OutputStream outputStream clientSocket.getOutputStream()) {Scanner scannerNetWork new Scanner(inputStream);while (true) {System.out.println(输入要发送的数据);//1.读取数据String request scanner.next();//2.将request作为请求发送到服务器中通过\n标识请求内容request \n;outputStream.write(request.getBytes());//3.读取服务器返回的响应if (!scannerNetWork.hasNext()){break;}String response scannerNetWork.next();System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}2.TCP多线程使用
在上面的TCP回显代码中并不能使用于多线程的形势下。在服务器中应当有线程池之类的多线程状态中同时处理多个客户端发送过来的请求。 因此需要对服务器实现多线程解决问题。通过线程池的方式while循环中不断接收客户端发来的连接请求并将任务交予线程池解决。
public void start() throws IOException {System.out.println(服务器启动);ExecutorService pool Executors.newCachedThreadPool();//accept可以阻塞等待while (true) {Socket socketClient serverSocket.accept();pool.submit(new Runnable() {Overridepublic void run() {try{processConnection(socketClient);} catch (IOException e) {throw new RuntimeException(e);}}});}}总结
在本文中主要讲解了TCP和UDP两个协议之间的区别同时对UDP网络编程进行了最基础的创建。 源码☞本文源码