简介:
网络编程就是指多台主机之间的数据通讯操作。
网络的核心定义:有两台以上的电脑就称为网络。
如何生产更多的电脑并将其进行连接。
网络连接的目的不仅仅是进行电脑的串联,更多的是为了进行彼此之间的数据通讯,包括现在的网络游戏实质上还是网络通讯的问题,而在通讯的实现上就产生了一系列处理的协议:IP、TCP、UDP等,所谓的网络编程实际上实现的就是数据通讯操作,只是这个通讯操作需要分为客户端和服务器端。
那么针对于网络程序的开发就有了两种模型:
- C/S(Client/Server:客户端、服务器端):
要开发出两套程序,一套程序为客户端,一套为服务器端,如果服务器端发生了改变之后客户端也要进行更新处理,这种开发可以由开发者自定义传输协议,并且使用一些私密的端口所以安全性比较高,但是开发与维护成本比较高(两套程序,变一则都变);
- B/S(Browse/Server:浏览器、服务器端):
只开发服务器端的程序,而后利用浏览器作为客户端进行访问,这种开发与维护的成本较低(只有一套程序),但是由于使用的公共的HTTP协议,并且使用的公共的80端口,所以其安全性较低,现在的开发基本上以“B/S”结构为主;
C/S程序模型(TCP[可靠的数据连接]、UDP[不可靠的数据连接]):
TCP程序的基本实现:
TCP的程序开发是网络程序最基本的开发模型,其核心是使用两个类实现数据的交互处理:ServerSocket(服务器端)、Socket(客户端)
ServerSocket设置服务器连接端口,Socket需要指明服务器的地址与端口。
Echo模型
客户端有接收和输出操作,服务器端也有接收和输出操作。
实现一个Echo模型操作:
服务器端:
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class serverSocket {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(9999); // 设置服务器端的监听端口
System.out.println("等待客户端连接.......");
Socket client = server.accept(); // 有客户端的连接
// 首先需要先接收客户端发送的信息然后将信息发送回客户端
Scanner sc = new Scanner(client.getInputStream()); // 客户端输入流
sc.useDelimiter("\n"); // 等待输入
PrintStream out = new PrintStream(client.getOutputStream()); // 客户端输出流
boolean flag = true;
while(flag) {
if(sc.hasNext()) { // 如果有数据
String val = sc.next(); // 接收发送的数据
if("byebye".equalsIgnoreCase(val)) {
out.println("再见!");
flag = false;
}else {
out.println("【Ehco】" + val);
}
}
}
sc.close();
out.close();
client.close();
server.close();
}
}
客户端:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class socketClient { private static final BufferedReader KEY_INPUT = new BufferedReader(new InputStreamReader(System.in)); public static void main(String[] args) throws Exception { Socket client = new Socket("localhost",9999); // 定义服务器端的连接信息 // 现在客户端需要有输入与输出的操作 Scanner sc = new Scanner(client.getInputStream()); // 接收服务器端的输入内容 sc.useDelimiter("\n"); PrintStream out = new PrintStream(client.getOutputStream()); // 向服务器端输出内容 boolean flag = true; while (flag) { String input = getString("请输入发送的内容:").trim(); out.println(input); // 加换行 if(sc.hasNext()) { // 服务器端回应 System.out.println(sc.next()); } if("byebye".equalsIgnoreCase(input)) { flag = false; } } sc.close(); out.close(); client.close(); } public static String getString(String prompt) throws Exception{ System.out.print(prompt); String str = KEY_INPUT.readLine(); return str; } }输出结果:
以上就是最基本的客户端与服务器端的操作实现。
多线程与网络编程:
上面的程序虽然实现了网络程序的开发,但是整个程序只能为一个线程提供Echo服务。
如果已经有一人连接了服务器,而还有其余的人想要连接服务器,那么就需要等待连接,只有前面的连接断开才能进行下一个连接,但是因为上面程序的客户端结束后服务器端会一起结束,所以导致了从开始到结束都只能为一个人提供服务。
现在就需要解决这种缺陷,就是将每一个访问服务器的客户端都使用线程对象处理,即:服务器上启动多个线程,每一个线程为每一个服务器端实现Echo服务支持。
修改服务器端程序:
package Demo_3_19_Echo模型; import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class serverSocket { private static class ClientThread implements Runnable{ private Socket client = null; // 描述每一个不同的客户端 private Scanner sc = null; PrintStream out = null; public boolean flag = true; public ClientThread(Socket client) throws Exception{ this.client = client; this.sc = new Scanner(client.getInputStream()); // 客户端输入流 this.sc.useDelimiter("\n"); // 等待输入 this.out = new PrintStream(client.getOutputStream()); // 客户端输出流 } @Override public void run() { while(this.flag) { if(this.sc.hasNext()) { // 如果有数据 String val = this.sc.next(); // 接收发送的数据 if("byebye".equalsIgnoreCase(val)) { out.println("再见!"); this.flag = false; }else { out.println("【Ehco】" + val); } } } try { sc.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(); } }
上面的代码启动了一个服务器端和两个客户端,可以发现两个客户端可以同时进行访问。
UDP(基于网络报)网络程序实现:
实现UDP的网络程序需要两个类:DatagramPacket(包含的数据内容)、DatagrmSocket(网络的发送与接收);
数据报就像发送的短消息一样,客户端是否接收到与发送者无关。
UDP服务器端:
package Demo_3_20_UDPServer;
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); // 监听端口为9000
String str = "www.baidu.com"; // 要发送的消息
DatagramPacket pac = new DatagramPacket(str.getBytes(),0,str.length(),InetAddress.getByName("localhost"),9999); // 发送数据,连接到9999端口
server.send(pac); // 发送消息
System.out.println("消息发送完毕.......");
}
}
客户端:
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 pac = new DatagramPacket(data,data.length); // 接收数据
System.out.println("客户端等待接收消息.......");
client.receive(pac); // 接收消息,所有的消息都在data字节数组之中
System.out.println("接收到的消息内容为:" + new String(data,0,pac.getLength()));
client.close();
}
}
输出结果:
先启动客户端,然后启动服务器端就能发送消息过去;
UDP发送的数据是不可靠的,但是TCP需要保证可靠的连接,所以需要的服务器的资源更多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)