Java网络编程
网络编程指多台主机之间的数据通讯操作
一、网络编程简介
**网络的核心定义:**有两台以上的计算机就成为网络
网络连接的目的不仅仅是为了进行电脑的串联,更多的情况下是为了进行彼此之间的数据通讯
在通讯的实现上产生了一系列的处理协议:IP、TCP、UDP等等
网络编程实际上实现的就是数据的通讯操作,只不过此通讯操作需要分为客户端与服务器端
针对网络程序的开发有两种模型:
- C/S(Client/Server、客户端与服务器端):要开发出两套程序,一套为客户端,一套为服务器端(服务器端发生改变后客户端也要进行更新改变)
- 这种开发可以由开发者自定义传输协议,并且使用一些比较私密的端口,安全性比较高,但是开发与维护成本较高
- B/S(Browse/Server、浏览器与服务器端):只开发一套服务器端的程序,之后利用浏览器作为客户端进行访问
- 这种开发和维护的成本较低,但是其使用的是公共的HTTP协议,并且使用是公共的80端口,所以安全性较差,现在的开发基本上以“B/S”结构为主
二、Echo程序模型
1、TCP程序的基本实现
TCP的程序开发是网络程序的最基本的开发模型,其核心的特点是使用两个类实现数据交互处理:ServerSocket(服务器端)、Socket(客户端)
ServerSocket的主要目的是设置服务器的监听端口,而 Socket需要指明要连接的服务器地址与端口
2、Echo程序实现
实现服务器端的定义
public class EchoServer {
public static void main(String[] args) throws Exception{
ServerSocket serverSocket = new ServerSocket(9999); //设置服务器端口
System.out.println("等待客户连接...");
Socket client = serverSocket.accept(); //有客户连接
Scanner scanner = new Scanner(client.getInputStream()); //客户端输入流
scanner.useDelimiter("\n"); //设置分隔符
PrintStream writer = new PrintStream(client.getOutputStream()); //客户端输出流
boolean flag = true; //循环标记
while (flag){
if (scanner.hasNext()){ //现在有数据发送
String value = scanner.next().trim(); //接收发送的数据
if ("byebye".equalsIgnoreCase(value)){
writer.println("再见");
flag = false; //结束循环
} else {
writer.println("[ECHO]" + value);
}
}
}
client.close();
writer.close();
scanner.close();
}
}
实现客户端
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 scanner = new Scanner(client.getInputStream()); //接收服务器的输入内容
scanner.useDelimiter("\n");
PrintStream writer = new PrintStream(client.getOutputStream()); //向服务器端发送内容
boolean flag = true;
while (flag){
String input = getString("请输入要发送的内容:").trim();
out.println(input);
if (scanner.hasNext()){
writer.println(scanner.next());
}
if ("byebye".equalsIgnoreCase(input)){
flag = false;
}
}
scanner.close();
writer.close();
client.close();
}
public static String getString(String prompt) throws Exception{
out.println(prompt);
String str = KEYBOARD_INPUT.readLine();
return str;
}
}
如果要进行程序测试,最好的方法是直接使用telnet命令,但是此命令默认为不开的状态,如果要使用,则需要单独开启
打开过程:在控制面板中 程序 中的 启动或关闭Windows功能 处的 telnet客户端
之后打开cmd输入 telnet 即可进入
然后输入 open localhost 9999
之后控制台就可以进行操作了
这样就玩成了一个最基础的服务器端和客户端的数据通讯
3、BIO处理模型
单线程服务器开发本身就是一种不合理的做法,此时最好的解决方案是将每个连接到服务器上的客户端都用过一个相乘对象来进行处理,即:服务器上启动多线程,每个线程单独为一个客户端实现Echo服务支持
public class EchoServer {
public static void main(String[] args) throws Exception{
ServerSocket serverSocket = new ServerSocket(9999); //设置服务器端口
System.out.println("等待客户连接...");
boolean flag = true; //循环标记
while (flag){
Socket client = serverSocket.accept(); //有客户连接
new Thread(new ClientThread(client)).start();
}
serverSocket.close();
}
private static class ClientThread implements Runnable {
private Socket client = null;
private Scanner scanner = null;
private PrintStream writer = null;
boolean flag = true; //循环标记
public ClientThread(Socket client) throws Exception{
this.client = client;
scanner = new Scanner(client.getInputStream()); //客户端输入流
scanner.useDelimiter("\n"); //设置分隔符
writer = new PrintStream(client.getOutputStream()); //客户端输出流
}
@Override
public void run() {
while (flag){
if (scanner.hasNext()){ //现在有数据发送
String value = scanner.next().trim(); //接收发送的数据
if ("byebye".equalsIgnoreCase(value)){
writer.println("再见");
flag = false; //结束循环
} else {
writer.println("[ECHO]" + value);
}
}
}
try {
client.close();
writer.close();
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4、UDP程序
实现UDP程序需要两个类:DatagramPacket(数据内容)、DatagramSocket(网络发送与接收)
数据报就好比发送短消息一样,客户端是否接收到域发送者无关
实现UDP客户端
public class UDPClient {
public static void main(String[] args) throws Exception{
DatagramSocket client = new DatagramSocket(9999);
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
System.out.println("客户端等待接收消息......");
client.receive(packet);
System.out.println("接收到的消息为:" + new String(data , 0 , packet.getLength()));
client.close();
}
}
//客户端等待接收消息......
//接收到的消息为:linlin
实现UDP服务端
public class UDPServer {
public static void main(String[] args) throws Exception{
DatagramSocket server = new DatagramSocket(9000);
String str = "linlin";
DatagramPacket packet = new DatagramPacket(str.getBytes(), 0, str.length() , InetAddress.getByName("localhost"),9999);
server.send(packet);
System.out.println("消息发送完毕!!!");
server.close();
}
//消息发送完毕!!!
UDP发送的数据一定是不可靠的,但是TCP由于需要保证可靠的来连接,所以需要的服务器资源较多