0%

Java学习基础-网络编程

一.网络编程入门
概述:在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以交换的数据

1.1 软件架构介绍
C/S架构:Client/Server
B/S架构:Browser/Server

1.2 网络通信协议
•什么是网络通信协议:计算机必须遵循的规则
•TCP/IP协议
TCP协议:Transmission Control Protocol,传输控制协议
IP协议:Internet Protocol,因特网协议

1.3 Java中支持的常见协议
java.net包提供两个协议
TCP传输控制协议:面向连接的协议(数据传输之前必须先建立连接,通过三次握手建立连接)
优点:保存数据完整,安全
缺点:消耗性能

UDP用户数据协议:面向无连接协议(数据传输时,不需要关心对方是否存在,只负责传输)
优点:性能较高
缺点:不能保证完整与安全性

1.4 网络编程三要素
a.网络通信协议
b.IP地址:每台连接到互联网的计算机的唯一标识,由32位二进制组成
c.端口号:一台计算机上不同软件的标识
端口号:一共0-65535个,1024是本机发出口,其他为随机高端口

1.5 计算机小知识
•IP地址的分类
IPv4:由32位二进制组成,2^32个地址
IPv6:由128位二进制组成,2^128个地址

•IP地址的相关命令
ipconfig/ifconfig:查看本机IP
ping/ping6:查看网络是否畅通

•特殊的IP地址
127.0.0.1(localhost):本机回环地址

1.6 InetAddress类的基本使用
a.InetAddress类代表IP地址
b.获取本机IP地址
InetAddress.getLocalHost();
c.获取其他机器IP地址
InetAddress.getByName(“”);
d.成员方法
String getHostName();获得主机名
String getHostAddress();获得IP地址字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public class Test_InetAddress {
public static void main(String[] args) throws UnknownHostException {
//获取本机IP地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//获取其他机器IP地址
InetAddress byName = InetAddress.getByName("www.baidu.com");
System.out.println(byName);

//成员方法
String hostName = byName.getHostName();
System.out.println(hostName);
String address = byName.getHostAddress();
System.out.println(address);
}
}

二.TCP通信程序
2.1 TCP通信分为客户端和服务器
客户端:用户电脑
服务器端:服务商电脑

2.2 TCP中两个重要的类
a.Socket类,代表客户端(套接字)
b.ServerSocket类,代表服务器端(服务器套接字)

2.3 Socket类的介绍和使用
•构造方法
public Socket(String ip,int port);//服务器IP地址,服务器端口号
此构造会根据传入的参数自动连接服务器:
若连接成功,则对象正常创建
若连接失败,则直接抛出异常

1
2
3
4
5
6
public class SocketDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.50.54",8080 );
System.out.println(socket);
}
}

•常用方法
public OutputStream getOutputStream();//获取连接通道中的输出流
public InputStream getInputStream();//获取连接通道中的输入流

public void shutDownOutput();//关闭连接通道中的输出流
public void shutDownInput();//关闭连接通道中的输入流

public void close();//关闭客户端对象

2.4 ServerSocket类的介绍和使用
•构造方法
public ServerSocket(int port);//指定服务器端使用的端口号

•常用的成员方法
public Socket accept();//接收连接到服务器的Socket对象,如果暂时没有客户端,该方法会阻塞
public Socket close();//关闭服务器对象

注意:服务器获取到客户端之后,也可以获得连接中的两个流,但是获取时是输入流还是输出流要相对服务器判断

2.5 简单的TCP通信实现(单向通信)
客户端给服务器发送信息,服务器不反馈。
客户端:
a.创建socket对象
b.获取输出流
c.调用输出流的write方法
d.释放资源
服务器:
a.创建ServerSocket对象
b.接收连接到的客户端对象
c.获取输入流
d.调用输入流的read方法
e.释放资源

UDP接收数据步骤:
①创建接收端的Socket对象(DatagramSocket)
DatagramSocket(int port)
②创建一个数据包,用于接收数据
DatagramPacket(byte[] buf,length)
③调用DatagramSocket对象的方法接收数据
void receive(DatagramPacket p)
④解析数据包,并把数据打印在控制台
byte[] getData()
int getLength()
⑤关闭接收端
void close()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

//TCP 方式
public class ServerSocketDemo_TCP {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Server running");
Socket accept = serverSocket.accept();
System.out.println("Client Coming");

InputStream in = accept.getInputStream();

byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("Client Said"+new String(bs,0,len));

in.close();
serverSocket.close();
}
}
//UDP方式
public class ServerSocketDemo_UDP {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(8888);
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys,length)

ds.receive(dp);

System.out.println(new String(dp.getData(),0,dp.getlength()));

ds.close();
}
}


public class SocketDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",8888 );
System.out.println("Connect Successful");
OutputStream out = socket.getOutputStream();

out.write("I am Client".getBytes());
System.out.println("Sent Successful");

out.close();
socket.close();
System.out.println("Client close");
}
}

2.6 简单的TCP通信实现(双向通信)
客户端给服务器发送信息,服务器接收后反馈。
客户端:
a.创建socket对象
b.获取输出流
c.调用输出流的write方法
===读取服务器回复的信息
d.获取输入流
e.调用输入流的read方法
f.释放资源

d.释放资源
服务器:
a.创建ServerSocket对象
b.接收连接到的客户端对象
c.获取输入流
d.调用输入流的read方法
====回信息
e.获取输出流
f.调用输出流的write方法
g.释放资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Server running");
Socket accept = serverSocket.accept();
System.out.println("Client Coming");

InputStream in = accept.getInputStream();

byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("Client Said"+new String(bs,0,len));

OutputStream outputStream = accept.getOutputStream();
outputStream.write("I am Server.".getBytes());

outputStream.close();
in.close();
serverSocket.close();
}
}


public class SocketDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",8888 );
System.out.println("Connect Successful");
OutputStream out = socket.getOutputStream();

out.write("I am Client".getBytes());
System.out.println("Sent Successful");

InputStream in = socket.getInputStream();

byte[] bs = new byte[1024];
int len = in.read(bs);
System.out.println("Server Said"+new String(bs,0,len));

in.close();
out.close();
socket.close();
System.out.println("Client close");
}
}

三.文件上传
3.1 分析
客户端:
读取文件FileInputStream
发送数据getOutputStream
a.创建Socket
b.获取输出流
c.创建文件的输入流
d.循环:一边读文件,一边发送
e.添加一句代码,告诉服务器文件发送完毕
f.获取输入流
g.读取服务器回复的信息
h.释放资源

服务器:
读取数据getInputStream
写入文件FileOutputStream
a.创建ServerSocket
b.获取客户端
c.获取输入流
d.创建文件输出流
e.循环:一边读数据,一边写文件
f.获取输出流
g.给客户端回信息
h.释放资源

3.2 文件上传案例实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
public class SocketDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
System.out.println("Connect Successful");
OutputStream outputStream = socket.getOutputStream();

FileInputStream fileInputStream = new FileInputStream("1.png");

byte[] bs = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bs)) != -1) {
outputStream.write(bs, 0, len);
}
socket.shutdownOutput();
System.out.println("File send successfle");

InputStream inputStream = socket.getInputStream();

len = inputStream.read(bs);
System.out.println(new String(bs,0,len));

inputStream.close();
fileInputStream.close();
outputStream.close();
socket.close();
System.out.println("Client close");
}
}


public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();

InputStream inputStream = accept.getInputStream();

FileOutputStream fileOutputStream = new FileOutputStream(System.currentTimeMillis()+".png");

byte[] bs = new byte[1024];
int len = 0;
while ((len = inputStream.read(bs)) != -1) {
fileOutputStream.write(bs, 0, len);
}

OutputStream outputStream = accept.getOutputStream();
outputStream.write("I am Server.".getBytes());

outputStream.close();
fileOutputStream.close();
inputStream.close();
accept.close();
serverSocket.close();
}
}


public class ServerSocketMultiDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();

FileOutputStream fileOutputStream = new FileOutputStream(System.currentTimeMillis() + ".png");

byte[] bs = new byte[1024];
int len = 0;
while ((len = inputStream.read(bs)) != -1) {
fileOutputStream.write(bs, 0, len);
}

OutputStream outputStream = accept.getOutputStream();
outputStream.write("I am Server.".getBytes());

outputStream.close();
fileOutputStream.close();
inputStream.close();
accept.close();
}
}
}


public class ServerSocketMultiDemo_Thread {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket accept = serverSocket.accept();

new Thread(() -> {
try {
InputStream inputStream = accept.getInputStream();

FileOutputStream fileOutputStream = new FileOutputStream(System.currentTimeMillis() + ".png");

byte[] bs = new byte[1024];
int len = 0;
while ((len = inputStream.read(bs)) != -1) {
fileOutputStream.write(bs, 0, len);
}

OutputStream outputStream = accept.getOutputStream();
outputStream.write("I am Server.".getBytes());
outputStream.close();
fileOutputStream.close();
inputStream.close();
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();

}
}
}

3.3 模拟BS架构服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket accept = serverSocket.accept();

new Thread(() -> {
try {

InputStream inputStream = accept.getInputStream();

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = bufferedReader.readLine();

String[] splits = line.split(" ");
String substring = splits[1].substring(1);
System.out.println(substring);

FileInputStream fileInputStream = new FileInputStream(substring);
OutputStream outputStream = accept.getOutputStream();

byte[] bs = new byte[1024];
int len = 0;
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
outputStream.write("Content-Type:text/html\r\n".getBytes());
outputStream.write("\r\n".getBytes());

while ((len = fileInputStream.read(bs)) != -1) {
outputStream.write(bs, 0, len);
}

outputStream.close();
inputStream.close();
accept.close();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
// serverSocket.close();
}
}
}

总结:
TCP协议特点:面向有连接(先建立连接,后建立数据)
UDP协议特点:面向无连接(只需要发送数据,不需关心对方是否存在)
TCP协议两个常用名称
Socket:客户端类
•构造方法
public Socket(String ip,int port);//服务器IP地址,服务器端口号
•常用方法
public OutputStream getOutputStream();//获取连接通道中的输出流
public InputStream getInputStream();//获取连接通道中的输入流
public void shutDownOutput();//关闭连接通道中的输出流
public void shutDownInput();//关闭连接通道中的输入流
public void close();//关闭客户端对象

ServerSocket:服务器类
•构造方法
public ServerSocket(int port);//指定服务器端使用的端口号
•常用的成员方法
public Socket accept();//接收连接到服务器的Socket对象,如果暂时没有客户端,该方法会阻塞
public Socket close();//关闭服务器对象

TCP协议单双向传输数据
TCP协议下文件上传案例
上传:客户端将文件发送至服务器,服务器保存到硬盘
下载:
a.客户端读取本地文件
b.通过流输出发送给服务器
c.服务器读取输入流数据
d.保存到服务器本地

TCP协议到BS案例:
不需要写客户端,使用浏览器访问服务器,