切换主题
二十、网络编程
一、什么是网络编程
在网络通信协议下,不同计算机上运行的程序,进行的数据传输
二、软件架构
三、网络编程三要素
1、IP
- 设备在网络中的地址,是唯一的标识
- 全称:
Internet Protocol
,是互联网协议地址,也称IP地址。是分配给上网设备的数字标签 - 父类:
IPV4
、IVP6
(1)IPV4
全称:Internet Protocal version 4
,互联网通信协议第四版
(2)IPV6
全称:Internet Protocal version 6
,互联网通信协议第六版
(3)特殊IP地址
127.0.0.1
,也是localhost
:是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在的本机
(4)InetAddress类的使用
方法名称 | 说明 |
---|---|
static InetAddress getByName(String host) | 确认主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 |
String getHostName() | 获取此IP地址的主机名 |
String getHostAddress() | 返回文本显示中的IP地址字符串 |
java
InetAddress hdq = InetAddress.getByName("hdq");
System.out.println(hdq); //hdq/192.168.1.198
String hostName = hdq.getHostName();
System.out.println(hostName); //hdq
String hostAddress = hdq.getHostAddress();
System.out.println(hostAddress); //192.168.1.198
2、端口号
- 应用程序在设备中唯一的标识
- 端口号:由两个字节表示的整数,取值范围:0~65535
- 其中0~1023之间的端口号用于一些知名的网络服务或者应用,自己使用1024以上的端口就可以了
- 一个端口号只能被一个应用程序使用
3、协议
- 计算机网络中,连接和通信的规则被称为网络通信协议
- 模型:
- OSI参考模型:世界互联协议标准,全球通信规范,但模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准

(1)UDP协议
- 用户数据报协议(User Datagram protocol)
- UDP是通信协议
- 速度快,有大小限制一次最多发送64k,数据不安全,易丢失数据
(2)TCP协议
- 传输控制协议TCP(Transmission Control Protocol)
- TCP协议是的通信协议
- 速度慢,没用大小限制,数据安全
四、UDP协议
1、发送数据
java
//创建DatagramSocket对象
DatagramSocket ds= new DatagramSocket();
String str="我真帅";
byte[] bytes=str.getBytes();
InetAddress address = InetAddress.getByName("hdq");
int port=10086;
//打包
DatagramPacket dp=new DatagramPacket(bytes,bytes.length,address,port);
//发送数据
ds.send(dp);
//释放资源
ds.close();
2、接收数据
java
//创建DatagramSocket对象,绑定发送数据的端口
DatagramSocket ds=new DatagramSocket(10086);
//接收数据的容器
byte[] bytes =new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
ds.receive(dp); //此处会阻塞,等待数据接收
//解析数据包
byte[] data=dp.getData();
int len=dp.getLength();
InetAddress address=dp.getAddress();
int port=dp.getPort();
System.out.println("接收到的数据是"+new String(data,0,len));
System.out.println("该数据是从"+address+"这台电脑中的"+port+"端口发送的");
//释放资源
ds.close();
3、三种通信方式
- 单播:使用
DatagramSocket
- 组播:使用
MulticastSocket
- 广播:使用
DatagramSocket
(1)单播
之前的代码就是单播
(2)组播
发送端
javaMulticastSocket ms=new MulticastSocket(); //...... InetAddress address = InetAddress.getByName("224.0.0.1"); //组播地址 //......
接收端
javaMulticastSocket ms=new MulticastSocket(10000); //...... InetAddress address = InetAddress.getByName("224.0.0.1"); //组播地址 ms.joinGroup(address); //......
(3)广播
和单播几乎一模一样,只需要改变
java
InetAddress address = InetAddress.getByName("255.255.255.255");
五、TCP协议
1、通信流程
客户端
创建客户端的
Socket
对象(Socket)与指定服务端连接javaSocket(String host , int port)
获取输出流,写数据
javaOutputStream getOutputStream()
释放资源
javavoid close()
服务器
创建客户端的
Socket
对象(ServerSocket)javaServerSocket(int port)
监听客户端连接,返回一个
Socket
对象javaSocket accept()
获取输入流,读数据,并把数据显示在控制台
javaInputStream getInputStream()
释放资源
javavoid close()
2、发送数据
java
//创建Socket对象
Socket socket=new Socket("192.168.1.198",5050);
//socket对象获取输出流
OutputStream os = socket.getOutputStream();
//写出数据
os.write("dsjids".getBytes());
//释放资源
os.close();
socket.close();
3、接受数据
java
//创建ServerSocket对象
ServerSocket ss=new ServerSocket(5050);
//监听客户端的链接
Socket socket=ss.accept();
//从连接通道获取输入流读取数据
InputStream is=socket.getInputStream();
//转换流
InputStreamReader isr=new InputStreamReader(is);
//缓冲流提高效率
BufferedReader br=new BufferedReader(isr);
int b;
while ((b=br.read())!=-1){
System.out.println((char) b);
}
socket.close();
ss.close();
4、三次握手和四次挥手
(1)三次握手
保持建立连接

(4)四次挥手
确保连接断开,且数据处理完毕

六、TCP通信练习
1、多发多收
- 客户端:多次发送数据
- 服务端:接收多次接收数据,并打印
Client
java
package a10.a1;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.198", 5001);
OutputStream os = socket.getOutputStream();
Scanner sc = new Scanner(System.in);
int i = 0;
while (true) {
if (i == 5) break;
i++;
System.out.println("请输入你要发送的信息:");
String message = sc.nextLine();
os.write(message.getBytes());
}
socket.close();
}
}
Server
java
package a10.a1;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
Socket socket = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int b;
while ((b = br.read()) != -1) {
System.out.println((char) b);
}
socket.close();
ss.close();
}
}
2、接收和反馈
- 客户端:发送一条数据,接收服务端反馈的消息并打印
- 服务器:接收数据并打印,再给客户端反馈消息
Client
java
package a10.a2;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.198", 5001);
OutputStream os = socket.getOutputStream();
String str = "呼叫服务端,收到请回答!!!";
os.write(str.getBytes());
socket.shutdownOutput();
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
int b;
while ((b = isr.read()) != -1) {
System.out.print((char) b);
}
socket.close();
}
}
Server
java
package a10.a2;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
Socket socket = ss.accept();
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
int b;
while ((b = isr.read()) != -1) {
System.out.print((char) b);
}
OutputStream os = socket.getOutputStream();
String str = "服务端收到!!!";
os.write(str.getBytes());
socket.close();
ss.close();
}
}
3、上传文件
(1)字节流方式处理
Client
java
package a10.a3;
import java.io.*;
import java.net.Socket;
import java.nio.charset.Charset;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.198", 5001);
// 读取本地文件 --采用字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("caogao\\huang.txt"));
// 使用字节缓冲输出流对外输出数据
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
//刷新此缓冲的输出流
bos.flush();
socket.shutdownOutput();
// 接收服务器的回写数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
// 释放资源
socket.close();
}
}
Server
java
package a10.a3;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
Socket socket = ss.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("caogao\\huang1.txt"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
socket.close();
ss.close();
}
}
(2)字符流方式处理
Client
java
package a10.a4;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.198", 5001);
// 读取本地文件 --采用字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("caogao\\huang.txt"));
// 使用字符缓冲输出流对外输出数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
bw.flush();
br.close();
socket.shutdownOutput();
// 接收服务器的回写数据
BufferedReader br2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = br2.readLine();
System.out.println(message);
br2.close();
// 释放资源
socket.close();
}
}
Server
java
package a10.a4;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
Socket socket = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("caogao\\huang1.txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
bw.flush();
bw.close();
// 回写
BufferedWriter message = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
message.write("上传成功");
message.newLine();
message.flush();
message.close();
br.close();
socket.close();
ss.close();
}
}
(3)多线程上传文件(频繁创建线程)
Client
java
package a10.a5;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.1.198", 5001);
// 读取本地文件 --采用字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("caogao\\mate60.png"));
// 使用字节缓冲输出流对外输出数据
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.flush();
socket.shutdownOutput();
//
//// 接收服务器的回写数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
// 释放资源
socket.close();
}
}
MyRunnable
java
package a10.a5;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunnable implements Runnable {
private Socket socket;
public MyRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-", "");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("caogao\\" + name + ".png"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Server
java
package a10.a5;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
while (true) {
Socket socket = ss.accept();
// 开启线程
new Thread(new MyRunnable(socket)).start();
}
}
}
(4)多线程上传文件(线程池)
代码只需修改Server类
java
package a10.a5;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5001);
ThreadPoolExecutor pool =new ThreadPoolExecutor(
3,
16,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
while (true) {
Socket socket = ss.accept();
// 开启线程
pool.submit(new MyRunnable(socket));
}
}
}