网络编程

1. 网络概念

把多台计算机通过物理线路连接起来,就形成了网络。目的在于交换数据和共享信息。

 1)网络通信的三要素

【1】IP地址:唯一标识网络上的每一台计算机。两台计算机之间通信的必备有素

【2】端口号:计算机中应用的标号(代表一个应用程序)

 0-1024系统使用或保留端口

常见端口:http:80 stmp: 25 ftp:21

有效端口0-65536,开发者可以的端口是1025-65536之间。一些第三方引用如mysql:3306 oracle:1251。

【3】通信协议:通信的规则TCP,UDP

2) 网络通信模型

 

 

 

IP地址分类

 

 

 

特殊IP

0.0.0.0:本机

127.0.0.1:本机回环地址,用于本机测试

255.255.255.255:当前子网,一般用于向当前子网广播信息

 

2.  InetAddress

InetAddress 表示IP地址。

 1 publicclass Test01 {
 2 
 3      publicstaticvoid main(String[] args) {
 4 
 5          // 获取本机IP地址
 6 
 7          InetAddress ip1;
 8 
 9          try {
10 
11               ip1 = InetAddress.getLocalHost();
12 
13               // USER-20180113BT/192.168.2.56
14 
15               System.out.println(ip1.toString());
16 
17              
18 
19               // 获取主机名称
20 
21               System.out.println(ip1.getHostName());
22 
23               System.out.println(ip1.getHostAddress());
24 
25              
26 
27          } catch (UnknownHostException e) {
28 
29               e.printStackTrace();
30 
31          }
32 
33      }
34 
35 }

3.  TCP编程

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

 

TCP通信步骤

[1]服务器启动ServerSocket作为通信的Server端,等待客户端链入。

[2]客户端创建Socket作为通信的Client端

[3]Client端链入Server端后建立可靠的双向的持续性的点对点的通讯连接,即可通信。

 

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

服务器端

 1 package cn.sxt01.net01;
 2 
 3  
 4 
 5 import java.io.IOException;
 6 
 7 import java.io.OutputStream;
 8 
 9 import java.net.ServerSocket;
10 
11 import java.net.Socket;
12 
13  
14 
15 publicclass Server01 {
16 
17      publicstaticvoid main(String[] args) {
18 
19         
20 
21          System.out.println("服务器启动...");
22 
23         
24 
25          // 【1】创建server socket
26 
27          ServerSocket serverSocket = null;
28 
29          Socket clientSocket = null;
30 
31          try {
32 
33         
34 
35               serverSocket = new ServerSocket(8000);
36 
37               // 【2】等待客户端的链入->阻塞式函数->监听8000端口,看是否有client链入
38 
39               clientSocket = serverSocket.accept();
40 
41              
42 
43               System.out.println(clientSocket.getInetAddress().getHostAddress()+"链入!");
44 
45         
46 
47               // 【3】给客户端主动发信息
48 
49               OutputStream out = clientSocket.getOutputStream();
50 
51              
52 
53               String msg = "hello 兄弟";
54 
55               byte[] buf = msg.getBytes("UTF-8");
56 
57               out.write(buf);
58 
59               clientSocket.shutdownOutput();
60 
61              
62 
63               out.close();
64 
65              
66 
67         
68 
69          } catch (IOException e) {
70 
71               e.printStackTrace();
72 
73          }
74 
75      }
76 
77 }

客户端

 

 1 package cn.sxt02.net01;
 2 
 3  
 4 
 5 import java.io.IOException;
 6 
 7 import java.io.InputStream;
 8 
 9 import java.net.Socket;
10 
11  
12 
13 publicclass Client01 {
14 
15     publicstaticvoid main(String[] args) {
16 
17         System.out.println("客户端运行...");
18 
19        
20 
21         // 【1】创建客户端socket
22 
23         Socket socket = null;
24 
25         try {
26 
27             socket = new Socket("192.168.2.56", 8000);
28 
29            
30 
31             // 【2】接收来自服务器的消息
32 
33             InputStream in = socket.getInputStream();
34 
35             byte[] buf = newbyte[1024];
36 
37             intlen = in.read(buf);
38 
39            
40 
41             String msg = new String(buf, 0, len, "UTF-8");
42 
43             System.out.println(msg);
44 
45            
46 
47         } catch (IOException e) {
48 
49             e.printStackTrace();
50 
51         }
52 
53     }
54 
55 }

常见问题

[1]端口被占用

java.net.BindException: Address already in use: JVM_Bind

     at java.net.DualStackPlainSocketImpl.bind0(Native Method)

     at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)

     at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)

     at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)

     at java.net.ServerSocket.bind(ServerSocket.java:375)

     at java.net.ServerSocket.<init>(ServerSocket.java:237)

     at java.net.ServerSocket.<init>(ServerSocket.java:128)

     at cn.sxt01.net02.Server01.main(Server01.java:19)

 

[2]服务器未启动

java.net.ConnectException: Connection refused: connect

     at java.net.DualStackPlainSocketImpl.connect0(Native Method)

     at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)

     at cn.sxt02.net02.Client01.main(Client01.java:15)

 

[3]连接超时异常SocketTimeoutException

当网速很慢时,可能发生连接超时异常。

 

 

需求:在控制台输入用户名和密码,如果输入正确提示登录成功,否则登录失败。

 服务器端

 1 public class Test01 {
 2     public static void main(String[]args) throws IOException, ClassNotFoundException{
 3         
 4         System.out.println("服务器启动中...");
 5         ServerSocket serverSocket=new ServerSocket(11000);
 6         while(true){
 7             Socket clinetSocket=serverSocket.accept();
 8             MyThread myThread=new MyThread(clinetSocket);
 9             myThread.start();
10         }
11     }
12 }
 1 public class MyThread extends Thread {
 2 
 3     private Socket socket;
 4 
 5     public MyThread() {
 6         super();
 7     }
 8 
 9     public MyThread(Socket socket) {
10         super();
11         this.socket = socket;
12     }
13     @Override
14     public void run() {
15         InputStream in=null;
16         ObjectInputStream ois=null;
17         OutputStream out=null;
18         DataOutputStream dos=null;
19         
20         try {
21             //接收来自客户端的信息
22             in=socket.getInputStream();
23             ois=new ObjectInputStream(in);
24             User user= (User) ois.readObject();
25             socket.shutdownInput();
26             
27             String str;
28             if(user.getName().equals("111") && user.getPwd().equals("123")){
29                 str="成功登陆";
30             }else{
31                 str="用户名或密码错误,登陆失败";
32             }
33             //返回给客户端的信息
34             out=socket.getOutputStream();
35             dos=new DataOutputStream(out);
36             dos.writeUTF(str);
37             socket.shutdownOutput();
38             
39             in.close();
40             ois.close();
41             dos.close();
42             out.close();
43             socket.close();
44         } catch (ClassNotFoundException e) {
45             e.printStackTrace();
46         } catch (IOException e) {
47             e.printStackTrace();
48         }
49     }
50 }
 1 public class User implements Serializable {
 2 
 3     private static final long serialVersionUID = 4478328638580552366L;
 4     private String name;
 5     private String pwd;
 6 
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14 
15     public String getPwd() {
16         return pwd;
17     }
18 
19     public void setPwd(String pwd) {
20         this.pwd = pwd;
21     }
22 
23     public User() {
24         super();
25     }
26 
27     public User(String name, String pwd) {
28         super();
29         this.name = name;
30         this.pwd = pwd;
31     }
32 
33     @Override
34     public String toString() {
35         return "User [name=" + name + ", pwd=" + pwd + "]";
36     }
37 
38 }

客户端

 1 public class Test01 {
 2     public static void main(String [] args){
 3         
 4         Scanner sc=new Scanner(System.in);
 5         System.out.println("请输入登录名:");
 6         String name=sc.nextLine();
 7         
 8         System.out.println("请输入密码:");
 9         String pwd=sc.nextLine();
10         
11         User user=new User(name,pwd);
12         
13         try {
14             // 传输请求给服务器
15             Socket socket=new Socket("127.0.0.1",11000);
16             OutputStream out=socket.getOutputStream();
17             ObjectOutputStream oos=new ObjectOutputStream(out);
18             
19             oos.writeObject(user);
20             socket.shutdownOutput();
21             
22             //接收来自服务器的信息
23             InputStream in=socket.getInputStream();
24             DataInputStream dis=new DataInputStream(in);
25             
26             String str=dis.readUTF();
27             System.out.println(str);
28             
29             
30         } catch (UnknownHostException e) {
31             e.printStackTrace();
32         } catch (IOException e) {
33             e.printStackTrace();
34         }
35         
36         
37     }
38 }
 1 public class User implements Serializable {
 2 
 3     private static final long serialVersionUID = 4478328638580552366L;
 4     private String name;
 5     private String pwd;
 6 
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14 
15     public String getPwd() {
16         return pwd;
17     }
18 
19     public void setPwd(String pwd) {
20         this.pwd = pwd;
21     }
22 
23     public User() {
24         super();
25     }
26 
27     public User(String name, String pwd) {
28         super();
29         this.name = name;
30         this.pwd = pwd;
31     }
32 
33     @Override
34     public String toString() {
35         return "User [name=" + name + ", pwd=" + pwd + "]";
36     }
37 
38 }

4.  UDP编程

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

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器

 

UDP步骤:

[1]创建一个DatagramSocket用于表示发送端,通过send方法发送数据报

[2]创建一个DatagramSocket用于表示接收端,通过receive方法接收数据报

 先运行接收端,再运行发送端!!!

需求:完成一次单向的UDP通信。

发送端

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          // 发送端:主动发送信息
 6 
 7          System.out.println("发送端开始发送信息...");
 8 
 9          // 【1】创建socket并指定发送数据的端口
10 
11          DatagramSocketsocket = null;
12 
13          try {
14 
15               socket = newDatagramSocket(8000);
16 
17              
18 
19               // 【2】创建数据报包
20 
21               String msg = "hello B";
22 
23               byte[] buf = msg.getBytes("UTF-8");
24 
25               DatagramPacketdp = newDatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 9000);
26 
27              
28 
29               // 【3】发送
30 
31               socket.send(dp);
32 
33              
34 
35               // 【4】关闭
36 
37               socket.close();
38 
39          } catch (SocketExceptione) {
40 
41               e.printStackTrace();
42 
43          } catch (UnsupportedEncodingExceptione) {
44 
45               e.printStackTrace();
46 
47          } catch (UnknownHostExceptione) {
48 
49               e.printStackTrace();
50 
51          } catch (IOExceptione) {
52 
53               e.printStackTrace();
54 
55          }
56 
57      }

接收端

 1 public static void main(String[] args) {
 2 
 3          // 接收端:接收信息
 4 
 5          System.out.println("启动接收端...");
 6 
 7          // 【1】创建一个DatagramSocket
 8 
 9          DatagramSocketsocket = null;
10 
11          try {
12 
13               socket = newDatagramSocket(9000);
14 
15               // 【2】接收消息
16 
17               byte[] buf = newbyte[1024];
18 
19               DatagramPacketdp = newDatagramPacket(buf, buf.length);
20 
21               System.out.println("等待接收信息...");
22 
23               socket.receive(dp);
24 
25               System.out.println("接收完成...");
26 
27              
28 
29               // 处理接收的信息
30 
31               String msg = new String(buf, 0, dp.getLength(), "UTF-8");
32 
33               System.out.println(msg);
34 
35              
36 
37          } catch (SocketExceptione) {
38 
39               e.printStackTrace();
40 
41          } catch (IOExceptione) {
42 
43               e.printStackTrace();
44 
45          }
46 
47      }

需求:实现双向通信

发送端

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          // 发送端:主动发送信息
 6 
 7          System.out.println("发送端开始发送信息...");
 8 
 9          Scanner sc = new Scanner(System.in);
10 
11          // 【1】创建socket并指定发送数据的端口
12 
13          DatagramSocketsocket = null;
14 
15          try {
16 
17               socket = newDatagramSocket(8000);
18 
19              
20 
21               for(;;) {
22 
23                    System.out.print("A说:");
24 
25                    String msg = sc.nextLine();
26 
27                    byte[] buf = msg.getBytes("UTF-8");
28 
29                    DatagramPacketdp = newDatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 9000);
30 
31                   
32 
33                    // 【3】发送
34 
35                    socket.send(dp);
36 
37                   
38 
39                   
40 
41                    // 接收消息
42 
43                    byte[] revBuf = newbyte[1024];
44 
45                    DatagramPacketrevDp = newDatagramPacket(revBuf,revBuf.length);
46 
47                    socket.receive(revDp);
48 
49                    String revStr = newString(revBuf, 0, revDp.getLength(), "UTF-8");
50 
51                    System.out.println(dp.getAddress().getHostName()+":"+revStr);
52 
53               }
54 
55              
56 
57          } catch (SocketExceptione) {
58 
59               e.printStackTrace();
60 
61          } catch (UnsupportedEncodingExceptione) {
62 
63               e.printStackTrace();
64 
65          } catch (UnknownHostExceptione) {
66 
67               e.printStackTrace();
68 
69          } catch (IOExceptione) {
70 
71               e.printStackTrace();
72 
73          }finally {
74 
75               // 【4】关闭
76 
77               socket.close();
78 
79          }
80 
81      }

接收端

 1     public static void main(String[] args) {
 2 
 3          // 接收端:接收信息
 4 
 5          System.out.println("启动接收端...");
 6 
 7          Scannersc = new Scanner(System.in);
 8 
 9          // 【1】创建一个DatagramSocket
10 
11          DatagramSocketsocket = null;
12 
13         
14 
15          try {
16 
17               socket = newDatagramSocket(9000);
18 
19              
20 
21               for(;;) {
22 
23                    // 接收信息
24 
25                    byte[] buf = newbyte[1024];
26 
27                    DatagramPacketdp = newDatagramPacket(buf, buf.length);
28 
29                    socket.receive(dp);
30 
31                    String msg = new String(buf, 0, dp.getLength(), "UTF-8");
32 
33                    System.out.println(dp.getAddress().getHostName()+":"+msg);
34 
35                   
36 
37                    // 发送信息
38 
39                    System.out.println("B说:");
40 
41                    String sendMsg = sc.nextLine();
42 
43                    byte[] sendBuf = sendMsg.getBytes("UTF-8");
44 
45                    DatagramPacketsendDp = newDatagramPacket(sendBuf, 0, sendBuf.length, dp.getAddress(), dp.getPort());
46 
47                    socket.send(sendDp);
48 
49               }
50 
51              
52 
53          } catch (SocketExceptione) {
54 
55               e.printStackTrace();
56 
57          } catch (IOExceptione) {
58 
59               e.printStackTrace();
60 
61          }finally {
62 
63               socket.close();
64 
65          }
66 
67      }

 

posted @ 2019-05-10 21:58  他也就火三年  阅读(224)  评论(0编辑  收藏  举报