Java基础(六十一)-网络编程

网络通讯

所谓的网络编程指的就是多台主机之间的数据通讯操作。

1:网络编程简介

网络的核心定义在于:有两台以上的电脑就称为网络。实际上在世界上生产第一台电脑之后就有人开始去思考如何可以将更多的电脑生产出来并且将其进行有效的连接。

网络连接的目的不仅仅事为了进行电脑的串联,更多的情况下事为了进行彼此之间的数据通讯。包括现在所谓的网络游戏本质上还是网络通讯的问题,而在通讯的实现上产生了一系列的处理协议:IP,TCP , UDP等,也就是说所谓的网络编程实际上实现的就是一个数据的通讯操作而已,只不过这个通讯的操作需要分为:客户端与服务器端。

于是针对网络程序的开发有两种模型:

C/S(Client/Server,客户端与服务器端)

要开发出两套程序,一套程序为客户端,另一套为服务器端,如果现在服务器端发生了改变之后客户端也应该进行更新处理,这种开发可以由开发者自定义传输协议,并且使用一些比较私密的端口,所以安全性事比较高的,但是开发与维护成本比较高;

B/S(Browse/Server,浏览器与服务器端)

只开发一套服务器端的程序,而后利用浏览器作为客户端进行访问,这种开发与维护的成本较低(只有一套程序),但是由于其使用的是公共的HTTP协议并且使用的公共的80端口,所以安全性相对较差,现在的开发基本上以B/S为主。

2:C/S程序模型,分为两种开发:TCP(可靠的数据连接),UDP(不可靠的数据连接)

3:TCP程序的基本实现

【所有的服务器如果在电脑上一定有一个所谓的监听端口,端口可以实现所有客户请求的连接(所有的端口监听住了,那么你所传的数据也就全都知道了)

在整个服务器端里面,如果我想要指派这样一个端口,那么通过一个程序类,叫做ServerSocket,告诉你我到底应该在哪个端口进行监听;

客户端所有的操作形式通过Socket描述,它的目标是帮助客户端找到

在拂去其里边有一个描述客户的操作,告诉你向哪个客户进行输出。

总结:服务端通过Socket来描述具体的客户,而客户端只是通过Socket找到我们的服务端。

Echo模型

客户端的输出对服务器端就是一个输入操作控制,而服务器端的输出控制就是客户端的输入处理。】

TCP的程序开发是网络程序的最基本的开发模型,其核心的特点是使用两个类实现数据的交互处理:ServerSocket(服务器),Socket(客户端)。
在这里插入图片描述

ServerSocket的主要目的是设置服务器的监听端口,而Scoket需要指明要连接的服务器地址与端口,下面实现一个最简单的数据处理操作,即:Echo程序实现

在这里插入图片描述

案例:实现客户端的定义


import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class EchoServer {
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(9999) ; // 设置服务器端的监听端口
		System.out.println("等待客户端连接.............");
		Socket client = server.accept() ; // 有客户端连接
		// 首先需要先接收客户端发送来的信息,而后才可以将信息处理之后发送回客户端
		Scanner scan = new Scanner(client.getInputStream()) ; 	// 客户端输入流
		scan.useDelimiter("\n") ; // 设置分隔符
		PrintStream out = new PrintStream(client.getOutputStream()) ; // 客户端输出流
		boolean flag = true ; // 循环标记
		while (flag) {
			if(scan.hasNext()) {	// 现在有数据发送
				String val = scan.next().trim() ; // 接收发送的数据
				if ("byebye".equalsIgnoreCase(val)) {
					out.println("ByeByeBye....");
					flag = false ; // 结束循环
				} else {
					out.println("【ECHO】" + val);
				}
			}
		}
		scan.close();
		out.close();
		client.close();
		server.close();
	}
}

案例:客户端代码

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class EchoClient {
	private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)) ;
	public static void main(String[] args) throws Exception {
		Socket client = new Socket("localhost",9999) ; // 定义服务端的连接信息
		// 现在的客户端需要有输入与输出的操作支持,所以依然要准备出Scanner与PrintWriter 
		Scanner scan = new Scanner(client.getInputStream()) ; // 接收服务器端的输入内容
		scan.useDelimiter("\n") ;
		PrintStream out = new PrintStream(client.getOutputStream()) ; // 向服务器端发送内容
		boolean flag = true ;
		while(flag) {
			String input = getString("请输入要发送的内容:").trim() ;
			out.println(input); // 加换行
			if (scan.hasNext()) {	// 服务器端有回应了
				System.out.println(scan.next());
			}
			if ("byebye".equalsIgnoreCase(input)) {
				flag = false ;
			}
		}
		scan.close();
		out.close();
		client.close(); 
	}
	public static String getString(String prompt) throws Exception {
		System.out.print(prompt);
		String str = KEYBOARD_INPUT.readLine() ;
		return str ;
	}
}

此时就实现了一个最基本的客户端与服务器端之间的数据通讯操作。

4:多线程与网络编程(TCP与多线程 )

现在尽管已经实现了一个标准的网络程序开发,但是在整个的开发过程之中杉树程序存在严重的性能缺陷,因为该服务能够为一个线程提高Echo服务,如果现在的服务器需要有多人进行连接访问的时候那么其他的使用着将无法连接(等待连接)/

所以现在就可以发现单线程的服务开发本身就是一种不合理的做法,那么此时最好的解决方案将每一个连接服务器上的客户端都通过一个线程对象来进行处理。即:服务器上启动多个线程,每一个线程单独为每一个客户端实现Echo服务支持。

在这里插入图片描述

案例:修改服务器程序


import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class EchoServer {
	private static class ClientThread implements Runnable {
		private Socket client = null ; // 描述每一个不同的客户端
		private Scanner scan = null ; 
		private PrintStream out = null ;
		private boolean flag = true ; // 循环标记
		public ClientThread(Socket client) throws Exception {
			this.client = client ;
			this.scan = new Scanner(client.getInputStream()) ; 	// 客户端输入流
			this.scan.useDelimiter("\n") ; // 设置分隔符
			this.out = new PrintStream(client.getOutputStream()) ; // 客户端输出流
		}
		@Override
		public void run() {
			while (this.flag) {
				if(scan.hasNext()) {	// 现在有数据发送
					String val = scan.next().trim() ; // 接收发送的数据
					if ("byebye".equalsIgnoreCase(val)) {
						out.println("ByeByeBye....");
						this.flag = false ; // 结束循环
					} else {
						out.println("【ECHO】" + val);
					}
				}
			}
			try {
				scan.close();
				out.close();
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	} 
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(9999) ; // 设置服务器端的监听端口
		System.out.println("等待客户端连接.............");
		// 首先需要先接收客户端发送来的信息,而后才可以将信息处理之后发送回客户端
		boolean flag = true ; // 循环标记
		while (flag) {
			Socket client = server.accept() ; // 有客户端连接
			new Thread(new ClientThread(client)).start();
		}
		server.close(); 
	}
}

5:数据报发送与接收

在这里插入图片描述

案例:实现一个UDP客户端

import java.net.DatagramPacket;
import java.net.DatagramSocket;
 
public class UDPClient {
	public static void main(String[] args) throws Exception { // 接收数据信息
		DatagramSocket client = new DatagramSocket(9999); // 连接到9999端口
		byte data[] = new byte[1024]; // 接收消息
		DatagramPacket packet = new DatagramPacket(data, data.length);// 接收数据
		System.out.println("客户端等待接收发送的消息........");
		client.receive(packet); // 接收消息,所有的消息都在data字节数组之中
		System.out.println("接收到的消息内容为:" + new String(data, 0, packet.getLength()));
		client.close(); 
	}
}

范例:实现UDP服务端

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {
	public static void main(String[] args) throws Exception {
		DatagramSocket server = new DatagramSocket(9000); // 连接到9999端口
		String str = "www.mldn.cn"; // 要发送的消息的内容
		DatagramPacket packet = new DatagramPacket(str.getBytes(), 0, str.length(), InetAddress.getByName("localhost"),
				9999);// 发送数据
		server.send(packet); // 发送消息
		System.out.println("消息发送完毕.....");
		server.close();
	}
}

UDP发送的数据一定是不可靠的,但是TCP由于需要保证可靠的连接所以所需的服务器资源就越多

猜你喜欢

转载自blog.csdn.net/qq_35649064/article/details/84248016