网络编程

1 网络概念

1.1 网络通信三要素

  1. IP地址:唯一标识网络上的每一台计算机。两台计算机之间通信的必备有素
  2. 端口号:计算机中应用的标号(代表一个应用程序)
    1. 0-1024 为系统使用或保留端口;
    2. 常见端口:http:80,stmp:25,ftp:21;
    3. 有效端口0-65536,开发者可以的端口是1025-65536之间。一些第三方引用如 mysql:3306,Oracle:1251。
  3. 通信协议:通信的规则 TCP,UDP

1.2 网络通信模型

2 InetAddress

 1 public class Test01 {
 2     public static void main(String[] args) {
 3         // 获取本机IP地址
 4         InetAddress ip1;
 5         try {
 6             ip1 = InetAddress.getLocalHost();
 7             // 将打印计算机名以及IP地址
 8             System.out.println(ip1.toString());
 9             
10             // 获取主机名称
11             System.out.println(ip1.getHostName());
12             System.out.println(ip1.getHostAddress());
13             
14         } catch (UnknownHostException e) {
15             e.printStackTrace();
16         }
17     }
18 }

3 TCP 编程

TCP编程中,如果要完成通信,通信双方必须要创建 socket,通过 socket 完成通信。

TCP通信步骤:

  1. 服务器启动 ServerSocket 作为通信的 Server 端,等待客户端链入。
  2. 客户端创建 Socket 作为通信的 Client 端
  3. Client 端链入 Server 端后建立可靠的、双向的、持续性的、点对点的通讯连接,即可通信。

案例一:完成一次单向通信

服务器端:

 1 import java.io.IOException;
 2 import java.io.OutputStream;
 3 import java.net.ServerSocket;
 4 import java.net.Socket;
 5 
 6 public class Server01 {
 7     public static void main(String[] args) {
 8         
 9         System.out.println("服务器启动...");
10         
11         // 【1】创建server socket
12         ServerSocket serverSocket = null;
13         Socket clientSocket = null;
14         try {
15         
16             serverSocket = new ServerSocket(8000);
17             // 【2】等待客户端的链入->阻塞式函数->监听8000端口,看是否有client链入
18             clientSocket = serverSocket.accept();
19             
20             System.out.println(clientSocket.getInetAddress().getHostAddress()+"链入!");
21         
22             // 【3】给客户端主动发信息
23             OutputStream out = clientSocket.getOutputStream();
24             
25             String msg = "hello 兄弟";
26             byte[] buf = msg.getBytes("UTF-8");
27             out.write(buf);
28                         //输出结束后,要记得socket.shudownOutput()
29             clientSocket.shutdownOutput();
30             
31             out.close();
32         } catch (IOException e) {
33             e.printStackTrace();
34         }
35     }
36 }

客户端:

 1 import java.io.IOException;
 2 import java.io.InputStream;
 3 import java.net.Socket;
 4 
 5 public class Client01 {
 6     public static void main(String[] args) {
 7         System.out.println("客户端运行...");
 8         
 9         // 【1】创建客户端socket
10         Socket socket = null;
11         try {
12             socket = new Socket("192.168.2.56", 8000);
13             
14             // 【2】接收来自服务器的消息
15             InputStream in = socket.getInputStream();
16             byte[] buf = new byte[1024];
17             int len = in.read(buf);
18             
19             String msg = new String(buf, 0, len, "UTF-8");
20             System.out.println(msg);
21             // 读取结束后,socket.shutdownInput()
22                         socket.shutdownInput();
23         } catch (IOException e) {
24             e.printStackTrace();
25         }
26     }
27 }

案例二:双向通信,模拟登录验证,采用传输对象的方式

服务器:

 1 package objectTCP.server;
 2 
 3 import java.io.DataOutputStream;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.io.ObjectInputStream;
 7 import java.io.OutputStream;
 8 import java.net.ServerSocket;
 9 import java.net.Socket;
10 
11 import objectTCP.User;
12 
13 public class Server {
14     public static void main(String[] args) throws InterruptedException {
15         System.out.println("Server started");
16         try {
17                         //创建服务器端
18             ServerSocket server = new ServerSocket(8000);
19             Socket client = server.accept();
20             System.out.println(client.getInetAddress().getHostName() + " connected");
21                         //接收
22             InputStream in = client.getInputStream();
23             ObjectInputStream ois = new ObjectInputStream(in);
24             User user = (User)ois.readObject();
25             client.shutdownInput();
26             
27             System.out.println(user.toString());
28                         //发送
29             if(user.getUsr().equals("admin") && user.getPsw().equals("12345")) {
30                 OutputStream out = client.getOutputStream();
31                 DataOutputStream dos = new DataOutputStream(out);
32                 dos.writeUTF("验证成功!");
33                 client.shutdownOutput();
34             }else {
35                 OutputStream out = client.getOutputStream();
36                 DataOutputStream dos = new DataOutputStream(out);
37                 dos.writeUTF("密码、或用户名错误,验证失败!");
38                 client.shutdownOutput();
39             }
40             client.close();
41             server.close();
42         } catch (IOException e) {
43             e.printStackTrace();
44         } catch (ClassNotFoundException e) {
45             e.printStackTrace();
46         }
47     }
48 }

客户端:

 1 package objectTCP.client;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.io.ObjectOutputStream;
 7 import java.io.OutputStream;
 8 import java.net.Socket;
 9 import java.util.Scanner;
10 
11 import objectTCP.User;
12 
13 public class Client {
14     public static void main(String[] args) {
15         User user = new User();
16         Scanner input = new Scanner(System.in);
17         System.out.print("usrName: ");
18         user.setUsr(input.nextLine());
19         System.out.print("psw: ");
20         user.setPsw(input.nextLine());
21         try {
22             Socket server = new Socket("192.168.3.2", 8000);
23             OutputStream out = server.getOutputStream();
24             ObjectOutputStream oos = new ObjectOutputStream(out);
25             oos.writeObject(user);
26             server.shutdownOutput();
27             
28             InputStream in = server.getInputStream();
29             DataInputStream dis = new DataInputStream(in);
30             System.out.println(dis.readUTF());
31             server.shutdownInput();
32             server.close();
33             input.close();
34         }catch (IOException e) {
35             e.printStackTrace();
36         }
37     }
38 }

这里要注意,服务器端的 User 类和客户端的 User 类要处于一样的包路径下,且拥有一样的序列化 ID,不然会出现类型转换异常。

配合线程,可以实现多用户验证,效果如图:

4 UDP 编程

UDP 编程中,如果要完成通信,通信双方必须要创建 DatagramSocket,通过 DatagramSo-cket 完成通信。

DatagramPacket 数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息(字节数组,长度,目标ip,端口)从一台机器自动路由到另一台机器。TCP 类似于打电话,需要双方确认,而 UDP 类似于发短信,只要知道目的地即可发送。

UDP步骤:

  1. 创建一个DatagramSocket用于表示发送端,通过send方法发送数据报
  2. 创建一个DatagramSocket用于表示接收端,通过receive方法接收数据报

需求:两个客户端相互聊天

用户1:先接收消息再发送消息

 1 package UDPClient2;
 2 
 3 import java.io.IOException;
 4 import java.io.UnsupportedEncodingException;
 5 import java.net.DatagramPacket;
 6 import java.net.DatagramSocket;
 7 import java.net.InetAddress;
 8 import java.net.SocketException;
 9 import java.net.UnknownHostException;
10 import java.util.Scanner;
11 
12 public class Test {
13     public static void main(String[] args) {
14         Scanner input = new Scanner(System.in);
15         try {
16             // 指定此程序的端口
17             DatagramSocket socket = new DatagramSocket(4000);
18             // 指定接受端的ip
19             InetAddress desIp = InetAddress.getByName("192.168.2.138");
20             while(true) {
21                 //接收消息
22                 byte[] rcvBuf = new byte[1024];
23                 DatagramPacket rcvPack = new DatagramPacket(rcvBuf, rcvBuf.length);
24                 socket.receive(rcvPack);
25                 System.out.println(rcvPack.getAddress().getHostName() + " --> " + new String(rcvBuf, 0, rcvPack.getLength(), "utf8"));
26                 
27                 
28                 //发送消息
29                 System.out.print("Your msg --> ");
30                 String msg = input.nextLine();
31                 byte[] sndBuf = msg.getBytes("utf8");
32                 // 创建发送出的包,指定了内容、目的地ip、目的地端口
33                 DatagramPacket sndPack = new DatagramPacket(sndBuf, sndBuf.length, desIp, 3000);
34                 //发送
35                 socket.send(sndPack);
36             }
37         } catch (SocketException e) {
38             e.printStackTrace();
39         } catch (UnsupportedEncodingException e) {
40             e.printStackTrace();
41         } catch (UnknownHostException e) {
42             e.printStackTrace();
43         } catch (IOException e) {
44             e.printStackTrace();
45         }
46     }
47 }

用户2:先发送消息,再接收消息

 1 package UDPClient1;
 2 
 3 import java.io.IOException;
 4 import java.io.UnsupportedEncodingException;
 5 import java.net.DatagramPacket;
 6 import java.net.DatagramSocket;
 7 import java.net.InetAddress;
 8 import java.net.SocketException;
 9 import java.net.UnknownHostException;
10 import java.util.Scanner;
11 
12 public class Test {
13     public static void main(String[] args) {
14         Scanner input = new Scanner(System.in);
15         try {
16             // 指定此程序的端口
17             DatagramSocket socket = new DatagramSocket(3000);
18             // 指定接受端的ip
19             InetAddress desIp = InetAddress.getByName("192.168.2.138");
20             while(true) {
21                 //发送消息
22                 System.out.print("Your msg --> ");
23                 String msg = input.nextLine();
24                 byte[] sndBuf = msg.getBytes("utf8");
25                 // 创建发送出的包,指定了内容、目的地ip、目的地端口
26                 DatagramPacket sndPack = new DatagramPacket(sndBuf, sndBuf.length, desIp, 4000);
27                 //发送
28                 socket.send(sndPack);
29                 
30                 
31                 //接收消息
32                 byte[] rcvBuf = new byte[1024];
33                 DatagramPacket rcvPack = new DatagramPacket(rcvBuf, rcvBuf.length);
34                 socket.receive(rcvPack);
35                 System.out.println(rcvPack.getAddress().getHostName() + " --> " + new String(rcvBuf, 0, rcvPack.getLength(), "utf8"));
36             }
37         } catch (SocketException e) {
38             e.printStackTrace();
39         } catch (UnsupportedEncodingException e) {
40             e.printStackTrace();
41         } catch (UnknownHostException e) {
42             e.printStackTrace();
43         } catch (IOException e) {
44             e.printStackTrace();
45         }
46     }
47 }

实现效果:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券