一、概述
在学习Java基础的时候,有一章节就叫《网络编程》,那么何为网络编程呢?在此之前先了解一下何为计算机网络。
-
计算机网络:
简单地说就是将地理位置不同的设备通过通信线路连接起来,实现不同设备间的信息传递和资源共享的计算机系统。 -
网络编程:
实现不同计算机上程序之间进行数据交换的过程就叫网络编程。比如我们常用的QQ、微信,就是在不同设备之间进行数据交换,就属于网络编程。
二、网络通信三要素
互联网上的设备要进行通信,有三个要素。
-
IP:
是设备在网络中的唯一标识,也就是说,一个IP就有唯一的一台设备,根据IP,就可以找到唯一的一台设备。
找到了设备,知道了要跟谁通信了,那么要跟这台设备上的哪个程序进程通信呢?那么就需要根据端口来判断。
-
端口:
用来区分设备上运行的不同的进程。有效端口为 0 ~ 65535 ,其中 0 ~ 1024 是系统保留的端口。
根据IP + 端口,我们可以找到需要进行通信的设备和该设备上对应的进程,按道理此时就可以进行通信了,实际上不是这样的。比如你是说中文的,你找到的那台设备的那个进程只能识别英文,那么语言就不互通了。这时候就需要用到协议。
-
协议:
可以简单的理解协议就是通信规则。让不同设备进行通信时可以语言互通。常用的协议有TCP协议和UDP协议。
TCP | UDP |
---|---|
建立数据通道,可进行大量数据传输,效率较低,但安全可靠。 | 无需建立连接,使用数据包传递数据,每个数据包大小限制在64k,效率高,不可靠。 |
三、Java对网络编程的支持
Java对网络编程提供了良好的支持,其相关的类都在 java.net 包下。
-
InetAddress类:
这个类可以理解为就是表示IP。 -
套接字:
套接字 = IP + 端口 。通信的两端(客户端和服务端) 都需要有套接字,套接字之间利用IO进行数据传输。客户端和服务端使用的套接字不同,TCP和UDP使用的套接字也不同。如下表。
方式 | 客户端 | 服务端 |
---|---|---|
TCP | Socket | ServerSocket |
UDP | DatagramSocket、DatagramPacket | DatagramSocket、DatagramPacket |
四、Java网络编程小案例
1、使用UDP协议进行通信:
客户端(发送端)编程步骤:
- 创建发送端的socket对象;
- 创建数据,并把数据打包;
- 调用socket的发送方法发送数据;
- 释放资源。
public static void main(String[] args) throws Exception {
//1.创建发送端的socket对象
DatagramSocket socket = new DatagramSocket();
//2.封装键盘录入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null){
if ("886".equals(line))//如果输入886就停止服务
break;
//3.创建数据,并把数据打包
byte[] bys = line.getBytes();//创建数据
int length = bys.length;
InetAddress address = InetAddress.getByName("xxx.xxx.x.xxx");//IP
int port = 10086;//端口
DatagramPacket dp = new DatagramPacket(bys,length,address,port);//打包数据
//4.调用socket的发送方法发送数据
socket.send(dp);
}
//5.释放资源
socket.close();
}
服务端(接收端)编程步骤:
- 创建接收端的socket对象;
- 创建数据包,用来接收数据;
- 调用socket对象的接收方法接收数据;
- 解析数据。
public static void main(String[] args) throws Exception {
//1.创建接收端的socket对象
DatagramSocket ds = new DatagramSocket(10086);
while (true){
//2.创建一个数据包(接收容器)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//3.调用socket对象的接收方法接收数据
ds.receive(dp);//阻塞式方法
//4.解析数据包,显示在控制台
String s = new String(dp.getData(),0,dp.getLength());
System.out.println(dp.getAddress().getHostAddress()+":"+s);
}
}
其实这样就是一个简易的聊天室了,先开启服务端,然后开启客户端,在控制台用键盘录入数据,这些数据就会在服务端的控制台显示出来。我们可以用多线程改进一下,以达到启动一个main方法,又可以发送又可以接收的效果。代码如下:
public class SendThread implements Runnable{
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
//2.封装键盘录入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null){
if ("886".equals(line))
break;
//3.创建数据,并把数据打包
DatagramPacket dp = new DatagramPacket(
line.getBytes(),
line.getBytes().length,
InetAddress.getByName("xxx.xxx.x.xxx"),
12306);
//4.调用socket的发送方法发送数据
ds.send(dp);
}
//5.释放资源
ds.close();
}catch (IOException e){
e.printStackTrace();
}
}
public class ReceiveThread implements Runnable {
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true){
//2.创建一个数据包(接收容器)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//3.调用socket对象的接收方法接收数据
ds.receive(dp);//阻塞式方法
//4.解析数据包,显示在控制台
String s = new String(dp.getData(),0,dp.getLength());
System.out.println(dp.getAddress().getHostAddress()+":"+s);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
public class chatRoom {
public static void main(String[] args) throws Exception {
DatagramSocket send = new DatagramSocket();
DatagramSocket receive = new DatagramSocket(12306);
SendThread st = new SendThread(send);
ReceiveThread rt = new ReceiveThread(receive);
Thread t1 = new Thread(st);
Thread t2 = new Thread(rt);
t1.start();
t2.start();
}
}
以上就是通过多线程改进的简易的聊天室。
2、使用TCP协议进行通信:
客户端编程步骤:
- 创建发送端的socket对象;
- 获取输出流写数据;
- 释放资源。
public static void main(String[] args) throws Exception {
//1.创建发送端的socket对象
Socket socket = new Socket("xxx.xxx.x.xxx",2222);
//2.获取输出流写数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null){
if ("886".equals(line))
break;
bw.write(line);
bw.newLine();
bw.flush();
}
//3.释放资源
socket.close();
}
服务端编程步骤:
- 创建接收端的socket对象;
- 监听客户端连接;
- 获取输入流读取数据;
- 释放资源。
public static void main(String[] args) throws IOException {
//1.创建接收端的socket对象
ServerSocket serverSocket = new ServerSocket(2222);
//2.监听客户端连接
Socket socket = serverSocket.accept();
//3.获取输入流读取数据,输出到文本文件
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
String line = null;
while ((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
bw.flush();
}
//4.释放资源
bw.close();
socket.close();
}
总结:
- 网络编程三要素就是IP、端口、协议。
- 协议主要是UDP和TCP两种。不管使用何种协议,客户端和服务端都需要有socket对象。
- UDP协议是将数据打包,每个数据包大小限制为64k,不建立连接,传输数据不可靠,但效率高。
- TCP协议会建立连接通道,传输的数据大小无限制,安全可靠,但效率较低。
网友评论