0%

网络编程

一,网络中的三要素

1.1 ip地址

ip地址用于标识网络中的计算机设备

查看本机ip地址:cmd -> ipconfig

ipv4:由32位的二进制数组成,格式:xxx.xxx.xxx.xxx,最多可以标识42亿多个地址

ipv6:每16个字节为一组,共8组,格式:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx,每个x是16进制数

本机的ip地址是:127.0.0.1、localhost

1.2 端口号

端口号用于标识计算机中的应用

端口号的范围:0~65535

格式:ip地址:端口号

1.3 传输协议

数据在网络中传输时需要遵循的规则

在 java.net 包中定义了 UDP、TCP 协议实现数据传输时所需要的类

1.3.1 UDP

UDP:User Datagram Protocol,用户数据报协议

特点

  1. 不建立连接,发送者不会确认接收者是否存在
  2. 效率高
  3. 不可靠
  4. 应用:在线视频
  5. 代码:在发送数据时,数据必须和目标地址封装在同一个数据包中

核心类:

  1. DatagramPacket:数据包,封装了传输的数据,如果是发送者还需要将数据与目标地址都封装在里面
  2. DatagramSocket:封装了对数据包的发送和接收的类
1.3.2 TCP

TCP:Transfer Control Protocol,传输控制协议

特点:

  1. 通过三次握手保证建立了连接
  2. 速度慢
  3. 可靠的连接
  4. 应用:聊天、下载、上传

核心类:

  1. ServerSocket:服务端
  2. Socket:客户端

二,InetAddress

InetAddress 类是 java.net 包下的一个用于获取域名、ip地址的类

静态方法:

  1. getByName(String host):host 可以是域名 www.baidu.com,也可以是ip地址 10.11.52.36
  2. getLocalHost():获取本机的域名、ip
  3. getAllByName(String host):获取指定域名或者ip地址所对应的所有ip地址

三,UDP 通信

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
// 收
new Thread(){
@Override
public void run() {
try {
DatagramSocket ds = new DatagramSocket(7777);
while(true){
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b,0,b.length);
ds.receive(dp);
byte[] data = dp.getData();
System.out.println(new String(data));
}
}
catch (Exception e){
e.printStackTrace();
}
}
}.start();


// 发
new Thread(){
@Override
public void run() {
try {
while(true){
DatagramSocket ds = new DatagramSocket();
String msg = new Scanner(System.in).next();
byte[] data = msg.getBytes();
DatagramPacket dp = new DatagramPacket(data,0,data.length, InetAddress.getByName("10.11.52.36"),6666);
ds.send(dp);
}
}catch (Exception e){

e.printStackTrace();
}
}
}.start();

四,TCP 通信

服务端

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
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(1234);
Socket s = ss.accept();

// 收
new Thread(){
@Override
public void run() {
try{
while(true){
InputStream is = s.getInputStream();
byte[] data = new byte[1024];
int len = is.read(data);
System.out.println("服务器接收到了"+s.getInetAddress().getHostAddress()+":"+new String(data,0,len));
}
}catch (Exception e){

}
}
}.start();

// 发
new Thread(){
@Override
public void run() {
try {
while(true){
OutputStream os = s.getOutputStream();
String msg = new Scanner(System.in).next();
os.write(msg.getBytes());
}
}catch (Exception e){

}
}
}.start();
}

客户端

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
public static void main(String[] args)throws Exception {

Socket s = new Socket("10.11.52.36",1234);
// 收
new Thread(){
@Override
public void run() {
try {
while(true){
InputStream is = s.getInputStream();
byte[] data = new byte[1024];
int len = is.read(data);
System.out.println(new String(data));
}
}catch (Exception e){

}
}
}.start();
// 发
new Thread(){
@Override
public void run() {
try {
while(true){
OutputStream os = s.getOutputStream();
String msg = new Scanner(System.in).next();
os.write(msg.getBytes());
}
}catch (Exception e){

}
}
}.start();

}

4.1 聊天室

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
private static ArrayList<Socket> sockets;

public static void main(String[] args) throws Exception {
System.out.println("服务器开启");
sockets = new ArrayList<Socket>();
ServerSocket ss = new ServerSocket(7890);

new Thread(new Runnable() {
int count = 1;
@Override
public void run() {
try{
while(count <= 3){
Socket s = ss.accept();
sockets.add(s);
sendAll(s); // 谁在什么时候进入了聊天室
new Thread(new Runnable() {
@Override
public void run() {
try{
while(true){
InputStream is = s.getInputStream();
byte[] data = new byte[1024];
int len = is.read(data);
String msg = new String(data,0,len);
sendAll(s,msg); // 谁在什么时候说了什么
}
}catch (Exception e){

}
}
}).start();
count++;
}
}catch (Exception e){

}
}
}).start();
}

public static void sendAll(Socket s,String str) throws Exception{
String ip = s.getInetAddress().getHostAddress();
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
String msg = time + " " + ip + ":" + str;
log(msg);
for(Socket socket : sockets){
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
}
}


public static void sendAll(Socket s) throws Exception{
String ip = s.getInetAddress().getHostAddress();
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
String msg = ip + "在" + time + "加入了聊天室";
log(msg);
for(Socket socket : sockets){
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
}
}

public static void log(String msg) throws Exception{
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\86151\\Desktop\\log.txt",true));
bw.write(msg);
bw.newLine();
bw.flush();
}

4.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
public static void main(String[] args) throws Exception {
// 1.创建本地的文件输入流
FileInputStream fis = new FileInputStream("C:\\mine\\图片\\封面.png");
// 2.创建客户端对象
Socket socket = new Socket("10.11.52.36",8888);
// 3.创建网络输出流对象
OutputStream os = socket.getOutputStream();
// 4.使用本地的文件输入流对象读取图片
// 5.使用网络输出流对象输出图片
byte[] data = new byte[1024];
int len;
while((len = fis.read(data)) != -1){
os.write(data,0,len);
}

// 客户端无法接收服务器的回写数据
// 原因;本质上是服务器根本没有执行到回写的语句,必须在客户端发送完毕后,告知服务器,发送给服务器一个发送完毕的标记,服务器才能得知接收完毕
socket.shutdownOutput();

// 6.创建网络输入流对象
InputStream is = socket.getInputStream();
byte[] msg = new byte[20];
int length = is.read(msg);
System.out.println(new String(msg,0,length));


is.close();
os.close();
fis.close();
socket.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
// 1.创建服务器对象
ServerSocket ss = new ServerSocket(9996);
while(true){
// 2.接收客户端对象
Socket s = ss.accept();
new Thread(new Runnable() {
@Override
public void run() {
try{
// 3.创建网络输入流
InputStream is = s.getInputStream();
// 指定图片的名字
String filename = new SimpleDateFormat("yyyyMMddHHmmssSS").format(new Date())+new Random().nextInt(100000000)+".jpg";
// 5.创建本地文件输出流
FileOutputStream fos = new FileOutputStream("C:\\Users\\86151\\Desktop\\图片\\"+filename);
// 6.使用网络输入流读取客户端发来的数据
// 7.使用本地文件输出流向指定目录中写入数据
byte[] data = new byte[1024];
int len;
while((len = is.read(data)) != -1){
fos.write(data,0,len);
}
// 8.创建网络输出流
OutputStream os = s.getOutputStream();
os.write("上传成功".getBytes());
os.close();
fos.close();
is.close();
}catch (Exception e){
System.out.println("上传失败");
}
}
}).start();
}