zoukankan      html  css  js  c++  java
  • Java之网络编程笔记

    网络通讯要素:

    1.IP地址  

      IP地址:用于标记一台计算机的身份证。 IP地址由网络地址(确定网络)和主机地址(网络中的主机)组成。

                IP地址分为A类地址、B类地址、C类地址(常用)、D类地址、E类地址。

      子网掩码:为了区分网络地址和主机地址。  127.0.0.1(localhost)是本机地址。

      IPV4和IPV6:IPV4使用4个十进制数表示,即32位二进制。

       测试网卡:ping 127.0.0.1 若出现问题,就说明网卡出问题
        
    2.端口号
        web服务器:80
        mysql默认:3306

    3.传输协议
    UDP(要明确对方地址和端口)(只管发,不管收)
        *面向无连接
        *数据会被封包,包体积有限,限制在64K以内
        *因面向无连接,故为不可靠协议
        *速度快
    示例:聊天,视频会议,桌面共享

    TCP
        *面向连接
        *通过三次握手完成连接,是可靠协议
        *在连接中进行大数据量传输
        *必须建立连接,效率会稍低

    示例:打电话,下载

    4.SMTP:简单邮件传输协议 ,端口号是25.

       FTP:文件传输协议        ,端口号是21.

       Http:超文本传输协议     ,端口号是80.

    telnet用于连接远程计算机或者因特网计算机提供的服务。每个服务都会设定一个端口。

    和特定的服务进行通信: 在cmd中使用命令 telnet ip   port  。

    如果要连接因特网的服务,不仅要给出端口,还要给出计算机的名称,只有给出IP地址和端口号时,才能够请求服务,并接收到应答。


    URL和URI

    URI:统一资源标识符,用于标识一个web资源,包含了两个部分。

    (1)URL:统一资源定位符。能够精确的定位数据的URI

    (2)URN:统一资源名称。除了URL的URI

    在java中URI和URL是分开的两个类,URI类专门用于解析,URL用于通信。

    URL

    1.URI分类

    绝对和相对:

    (1)绝对URI是指有确定的协议。比如http,ftp。后面以/进行分隔

    (2)相对URI是没有scheme的。

    透明和不透明:

    (1)不透明URI是不能够被解析的URI。不透明URI是绝对URI。scheme后面的部分不是以/进行分割。

    分层和不分层:

    (1)分层是绝对透明URI或相对URI。

    所有的网页端口都是80.

    2.URI的作用:

    (1)解析

    URI的格式:

    [scheme:]scheme-specific-part[#fragment]

    scheme表示用的协议,可以是httphttpsftpfile等。

    scheme-specific-part是其余部分。

    进一步细分:

    [scheme:][//authority][path][?query][#fragment]

    常用方法:

    • getScheme()获得scheme;
    • getSchemeSpecificPart()
    • getPath()
    • getAuthority()

    (2)相对标识符和绝对标识符的转换

    resolve和relative函数。

    示例代码:

    任务1:取得特定网址的html代码。

    任务2:分析地址信息。

    任务3:绝对地址和相对地址转换

    1. package org.core;  
    2.   
    3. import java.net.*;  
    4. import java.util.*;  
    5.   
    6. public class URLTest1 {  
    7.   
    8.     public static void main(String[] args) throws Exception {  
    9.         URL url = new URL("http://www.ecnu.edu.cn");  
    10.         Scanner in = new Scanner(url.openStream());  
    11.         while (in.hasNextLine()) {  
    12.             String str = in.nextLine();  
    13.             System.out.println(str);  
    14.         }  
    15.   
    16.         URI uri = new URI("http://blog.csdn.net/xiazdong");  
    17.         System.out.println(uri.getScheme());  
    18.         System.out.println(uri.getSchemeSpecificPart());  
    19.         System.out.println(uri.getAuthority());  
    20.         System.out.println(uri.getUserInfo());  
    21.         System.out.println(uri.getHost());  
    22.         System.out.println(uri.getPort());  
    23.         System.out.println(uri.getPath());  
    24.         System.out.println(uri.getQuery());  
    25.         System.out.println(uri.getFragment());  
    26.   
    27.         String str = "/article/details/6705033";  
    28.         URI combined = uri.resolve(str);// 根据uri的路径把str变成绝对地址  
    29.         System.out.println(combined.getScheme()  
    30.                 + combined.getSchemeSpecificPart());  
    31.   
    32.         URI relative = uri.relativize(new URI(str));  
    33.         System.out.println(relative.getSchemeSpecificPart());  
    34.   
    35.     }  
    36.   
    37. }  


    URL和URLConnection

    URL的作用

    1.如果想要获取某个网页的html源代码,比如http://blog.csdn.net/xiazdong 则只需要:

    (1)URL url = new URL("http://blog.csdn.net/xiazdong");

    (2)Scanner in = new Scanner(url.openStream());

    即可.

    2.获取消息头信息

    • URLConnection connection = url.openConnection();
    • connection.getHeaderFields()返回一个Map<String,List<String>>
    • connection.getContentLength();
    • connection.getContentType();
    • connection.setDoOutput(true)获得输出流
    • connection.getOutputStream();
    • connection.getInputStream();

    代码示例:

    1. package org.core;  
    2.   
    3. import java.net.*;  
    4. import sun.misc.*;  
    5. import java.util.*;  
    6. import java.io.*;  
    7.   
    8. public class URLConnectionTest {  
    9.   
    10.     public static void main(String[] args) throws Exception {  
    11.         String urlName = "http://java.sun.com";  
    12.         URL url = new URL(urlName);  
    13.         URLConnection connection = url.openConnection();  
    14.         Map<String, List<String>> map = connection.getHeaderFields();  
    15.         for (Map.Entry<String, List<String>> entry : map.entrySet()) {  
    16.             String key = entry.getKey();  
    17.             List<String> value = entry.getValue();  
    18.             System.out.println(key + ":" + value);  
    19.         }     
    20.   
    21.     }  
    22.   
    23. }  



    在网页中如果要提交数据给web服务器,通常要把数据发送给web服务器,然后web服务器委派一个脚本对数据进行处理,返回一个相应。

    通常发送数据的方法有两种:get和post。

    (1)get方法是直接把数据跟在url的后面,以name=value进行传输,

    每个数据之间用&进行分割,value中的空格用+替换,非字母数字用%替换,并后跟两个16进制数,这种编码方式称为URL编码。URLEncoder和URLDecoder

    (2)post方法是通过URLConnection发送给服务器,编码方式和get一样。URLEncoder.encode(VALUE,"UTF-8");

    一般在传输中文时会运用编码和解码。

    示例:通过URLEncoder和URLDecoder编码和解码


    InetAddress  根据域名得到IP地址或名称

    没有构造方法,通过:

    (1)InetAddress i1 = InetAddress.getByName(String)返回一个InetAddress实例。

    (2)如果一个地址有多个ip地址,比如google,有3个ip地址,就调用InetAddress[] i2 = InetAddress.getAllByName(String);

    InetAddress.getLocalhost()获得本机的InetAddress实例。

    代码实例:

    1. package org.core;  
    2.   
    3. import java.net.InetAddress;  
    4.   
    5. public class InetAddressTest {  
    6.   
    7.     public static void main(String[] args) throws Exception{  
    8.         InetAddress local = InetAddress.getLocalHost();  
    9.         System.out.println("本机地址:"+local.getHostAddress());  
    10.         System.out.println("本机名称:"+local.getHostName());  
    11.         InetAddress[] remote = InetAddress.getAllByName("www.google.com");  
    12.         for(InetAddress a : remote)  
    13.         {  
    14.             System.out.println("地址:"+a.getHostAddress());  
    15.             System.out.println("名称:"+a.getHostName());  
    16.         }     
    17.     }  
    18. }  

    Socket(TCP)

    Socket是一个用于机器之间通信的类。

    Socket客户端:

    (1)Socket s = new Socket(ip,port);打开一个套接字,发送请求    

    (2)InputStream istream = s.getInputStream();接收数据

    (3)OutputStream ostream  = s.getOutputStream();发送数据

    需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲。

    Socket服务器:注意多个客户端同时访问服务器的问题:多线程

    (1)ServerSocket server = new ServerSocket(port);创建一个端口

    (2)Socket s = server.accept();        只有当有客户端请求并连接,函数才会返回

    (3)InputStream istream = s.getInputStream();接收数据

    (4)OutputStream ostream  = s.getOutputStream();发送数据

    需要用PrintWriter和Scanner进行包装,并且注意PrintWriter的自动缓冲。

    我们在使用PrintWriter时需要使用println()函数;


    当服务器或客户端任意一方请求结束通信,则立刻停止。

    问题1:在套接字中会发生阻塞的地方:

    (1)实例化Socket时,会阻塞。

    (2)在in.nextLine()类似操作时会阻塞。

    解决方法:

    (1)对于第一个问题,解决方法:

    • Socket s = new Socket();建立无连接socket
    • s.connect(new InetSocketAddress(host,port),timeout);设置超时。

    (2)对于第二个问题,解决方法是设置s.setSoTimeout(long)设置超时时间

    问题2:当客户端想要关闭套接字时,但却不能确定服务器是否还在发送数据,但是只要一关闭就立刻断开。

    解决方法:

    socket.shutdownOutput()关闭输出流

    socket.shutdownInput()关闭输入流

    半关闭示例代码:客户端发送hello给服务器,同时关闭输出流,服务器接收到后关闭输入流,等待5秒发送ECHO hello给客户端。

     Client:

    1. import java.net.*;  
    2. import java.io.*;  
    3. import java.util.*;  
    4. public class shutdownOutputClient {  
    5.   
    6.     public static void main(String[] args)throws Exception {  
    7.         Socket s = new Socket("localhost",8819);  
    8.         Scanner in = new Scanner(s.getInputStream());  
    9.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
    10.         out.println("Hello");//输出hello  
    11.         s.shutdownOutput(); //关闭输出流  
    12.         System.out.println("关闭连接");  
    13.         while(in.hasNextLine()){  
    14.             System.out.println(in.nextLine());  
    15.         }  
    16.         s.close();  
    17.     }  
    18.   
    19. }  


    Server:

    1. import java.net.*;  
    2. import java.io.*;  
    3. import java.util.*;  
    4. public class shutdownOutputServer {  
    5.   
    6.     public static void main(String[] args)throws Exception {  
    7.         ServerSocket server = new ServerSocket(8819);  
    8.         Socket s = server.accept();  
    9.         Scanner in = new Scanner(s.getInputStream());  
    10.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
    11.         String str = in.nextLine();  
    12.         System.out.println(str);  
    13.         s.shutdownInput();  
    14.         System.out.println("关闭输入流");  
    15.           
    16.         Thread.sleep(5000);  
    17.         out.println("Echo:"+str);  
    18.         s.close();  
    19.     }  
    20.   
    21. }  


    综合代码举例:实现一个简单的对等通信程序,通过多线程,一个线程接收数据,一个线程发送数据。

    用户1:

    1. import java.util.*;  
    2. import java.io.*;  
    3. import java.net.*;  
    4. public class Client{  
    5.     public static void main(String[]args)throws Exception{  
    6.         Socket s = new Socket("localhost",8819);  
    7.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
    8.         Thread t = new Thread(new Receive(s));  
    9.         t.start();  
    10.         //以下代码用于发送数据  
    11.         Scanner in = new Scanner(System.in);//键盘输入  
    12.         while(in.hasNextLine()){    //一直不断  
    13.             out.println(in.nextLine()); //发送键盘输入数据  
    14.         }  
    15.     }  
    16. }  
    17. class Receive implements Runnable   //这个类用于接收数据  
    18. {  
    19.     private Socket s;  
    20.     public Receive(Socket s)  
    21.     {  
    22.         this.s = s;  
    23.     }  
    24.     public void run()  
    25.     {  
    26.         try{  
    27.             Scanner in = new Scanner(s.getInputStream());   //in:接收数据  
    28.           
    29.             String str = null;  
    30.             while(true)  
    31.             {  
    32.                 str = in.nextLine();      
    33.                 System.out.println("服务器说:"+str);    //打印接收数据  
    34.             }  
    35.               
    36.         }  
    37.         catch(Exception e){}  
    38.     }  
    39. }  


    用户2:

    1. import java.util.*;  
    2. import java.io.*;  
    3. import java.net.*;  
    4. public class Server{  
    5.     public static void main(String[]args)throws Exception{  
    6.         ServerSocket server = new ServerSocket(8819);  
    7.         Socket s = server.accept();  
    8.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
    9.         Thread t = new Thread(new Receive1(s));  
    10.         t.start();  
    11.         //以下代码用于发送数据  
    12.         Scanner in = new Scanner(System.in);//键盘输入  
    13.         while(in.hasNextLine()){    //一直不断  
    14.             out.println(in.nextLine()); //发送键盘输入数据  
    15.         }  
    16.     }  
    17. }  
    18. class Receive1 implements Runnable  //这个类用于接收数据  
    19. {  
    20.     private Socket s;  
    21.     public Receive1(Socket s)  
    22.     {  
    23.         this.s = s;  
    24.     }  
    25.     public void run()  
    26.     {  
    27.         try{  
    28.             Scanner in = new Scanner(s.getInputStream());   //in:接收数据  
    29.           
    30.             String str = null;  
    31.             while(true)  
    32.             {  
    33.                 str = in.nextLine();      
    34.                 System.out.println("客户端说:"+str);    //打印接收数据  
    35.             }  
    36.               
    37.         }  
    38.         catch(Exception e){}  
    39.     }  
    40. }  


    以上的程序属于C/S,需要同时维护客户端和服务器的代码。

    B/S:浏览器和服务器,只需要维护一方代码即可。


    聊天工具使用UDP非常多,因为我们通常也会遇到我们发给另一个人一条消息,另一个人却没有收到的情况。

    DatagramPacket和DatagramSocket  数据报

    代码举例:实现服务器发送数据报到客户端。

    Client:

    1. package org.core;  
    2.   
    3. import java.net.*;  
    4. import java.io.*;  
    5. public class DatagramClient {  
    6.   
    7.     public static void main(String[] args) throws Exception{  
    8.         byte[]buf = new byte[1024];  
    9.         DatagramPacket packet = new DatagramPacket(buf,1024);  
    10.         DatagramSocket client = new DatagramSocket(9000);  
    11.         client.receive(packet);  
    12.         String str = new String(buf,0,packet.getLength());  
    13.         System.out.println(packet.getAddress().getHostName()+":"+str);  
    14.         client.close();  
    15.     }  
    16.   
    17. }  


    Server:

    1. package org.core;  
    2.   
    3. import java.net.DatagramPacket;  
    4. import java.net.DatagramSocket;  
    5. import java.net.InetAddress;  
    6.   
    7. public class DatagramServer {  
    8.   
    9.     public static void main(String[] args)throws Exception {  
    10.         DatagramSocket server = new DatagramSocket(3000);  
    11.         String str = "hello world";  
    12.         DatagramPacket packet = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getLocalHost(),9000);  
    13.         server.send(packet);  
    14.         server.close();  
    15.     }  
    16. }  

    QQ聊天应用

    Server端

    1. package org.xiazdong.server;  
    2.   
    3.   
    4. import java.awt.BorderLayout;  
    5. import java.awt.event.ActionEvent;  
    6. import java.awt.event.ActionListener;  
    7. import java.io.BufferedReader;  
    8. import java.io.InputStreamReader;  
    9. import java.io.PrintStream;  
    10. import java.net.InetAddress;  
    11. import java.net.ServerSocket;  
    12. import java.net.Socket;  
    13.   
    14. import javax.swing.JButton;  
    15. import javax.swing.JFrame;  
    16. import javax.swing.JPanel;  
    17. import javax.swing.JScrollPane;  
    18. import javax.swing.JTextArea;  
    19. import javax.swing.JTextField;  
    20.   
    21. public class Server3 extends JFrame{  
    22.     static JTextArea area;  
    23.     JTextField field;  
    24.     JButton button;  
    25.     static PrintStream writer;  
    26.     public Server3(){  
    27.         this.setTitle("服务器");  
    28.         this.setSize(400,500);  
    29.         area = new JTextArea(25,30);  
    30.         area.setEditable(false);  
    31.         field = new JTextField(20);  
    32.         button = new JButton("提交");  
    33.         JPanel panel = new JPanel();  
    34.         JScrollPane sp = new JScrollPane(area);  
    35.         this.add(sp,BorderLayout.CENTER);  
    36.         panel.add(field);  
    37.         panel.add(button);  
    38.         this.add(panel,BorderLayout.SOUTH);  
    39.         this.setVisible(true);  
    40.         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    41.           
    42.         button.addActionListener(new ActionListener(){  
    43.   
    44.             @Override  
    45.             public void actionPerformed(ActionEvent e) {  
    46.                 String text = field.getText();  
    47.                 writer.println(text);  
    48.                 area.append("我:"+text+" ");  
    49.                 field.setText("");  
    50.             }  
    51.               
    52.         });  
    53.     }  
    54.     public static void main(String[] args) throws Exception {  
    55.         Server3 s = new Server3();  
    56.         ServerSocket server = new ServerSocket(8899);  
    57.         System.out.println("开始监听...");  
    58.         Socket socket = server.accept();  
    59.         InetAddress address = socket.getInetAddress();  
    60.         String name = address.getLocalHost().getHostName();  
    61.         System.out.println(name+"已连接");  
    62.         BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
    63.         writer = new PrintStream(socket.getOutputStream(), true);  
    64.         while (true) {  
    65.             String line = null;  
    66.             line = reader.readLine();  
    67.             if (line != null) {   
    68.                     area.append("客户端:"+line+" ");  
    69.             }  
    70.   
    71.         }  
    72.     }  
    73.   
    74. }  


    Client端

    1. package org.xiazdong.client;  
    2. import java.awt.BorderLayout;  
    3. import java.awt.event.ActionEvent;  
    4. import java.awt.event.ActionListener;  
    5. import java.io.BufferedReader;  
    6. import java.io.InputStreamReader;  
    7. import java.io.OutputStream;  
    8. import java.io.PrintStream;  
    9. import java.io.PrintWriter;  
    10. import java.net.Socket;  
    11.   
    12. import javax.swing.JButton;  
    13. import javax.swing.JFrame;  
    14. import javax.swing.JPanel;  
    15. import javax.swing.JScrollPane;  
    16. import javax.swing.JTextArea;  
    17. import javax.swing.JTextField;  
    18.   
    19. public class Client3 extends JFrame{  
    20.   
    21.     static JTextArea area;  
    22.     JTextField field;  
    23.     JButton button;  
    24.     static PrintWriter writer;  
    25.     public Client3(){  
    26.         this.setTitle("客户端");  
    27.         this.setSize(400,500);  
    28.         area = new JTextArea(25,30);  
    29.         area.setEditable(false);  
    30.         field = new JTextField(20);  
    31.         button = new JButton("提交");  
    32.         JScrollPane sp = new JScrollPane(area);  
    33.         JPanel panel = new JPanel();  
    34.         this.add(sp,BorderLayout.CENTER);  
    35.         panel.add(field);  
    36.         panel.add(button);  
    37.         this.add(panel,BorderLayout.SOUTH);  
    38.         this.setVisible(true);  
    39.         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    40.           
    41.         button.addActionListener(new ActionListener(){  
    42.   
    43.             @Override  
    44.             public void actionPerformed(ActionEvent e) {  
    45.                 String text = field.getText();  
    46.                 writer.println(text);  
    47.                 area.append("我:"+text+" ");  
    48.                 field.setText("");  
    49.             }  
    50.               
    51.         });  
    52.     }  
    53.     public static void main(String[] args) throws Exception{  
    54.         Client3 c = new Client3();  
    55.         Socket socket = new Socket("127.0.0.1",8899);  
    56.         OutputStream out = socket.getOutputStream();  
    57.         BufferedReader reader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
    58.         writer = new PrintWriter(out,true);  
    59.         System.out.println("已经成功和服务器连接...");  
    60.         while(true){  
    61.             String line = reader1.readLine();  
    62.             area.append("服务器:"+line+" ");  
    63.         }  
    64.     }  
    65.   
    66. }  


    PrintWriter的autoflush

    如果PrintWriter writer = new PrintWriter(out,true);

    则调用println()、printf()、format()函数时会自动刷新,其他函数都不会,比如write()、print()函数时不会自动刷新

     网络编程常见异常


    第 1个异常是java.net.BindException:Address already in use: JVM_Bind。该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经被启动,并进行监 听。此时用netstat –an命令,可以看到一个Listending状态的端口。只需要找一个没有被占用的端口就能解决这个问题。 

    第 2个异常是java.net.ConnectException: Connection refused: connect。该异常发生在客户端进行new Socket(ip, port)操作时,该异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端 口进行监听。出现该问题,首先检查客户端的ip和port是否写错了,如果正确则从客户端ping一下服务器看是否能ping通,如果能ping通(服务 服务器端把ping禁掉则需要另外的办法),则看在服务器端的监听指定端口的程序是否启动,这个肯定能解决这个问题。 

    第3个异常是java.net.SocketException: Socket is closed,该异常在客户端和服务器均可能发生。异常的原因是己方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作。 

    第 4个异常是java.net.SocketException: (Connection reset或者Connect reset by peer:Socket write error)。该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而 引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。 

    第 5个异常是java.net.SocketException: Broken pipe。该异常在客户端和服务器均有可能发生。在第4个异常的第一种情况中(也就是抛出SocketExcepton:Connect reset by peer:Socket write error后),如果再继续写数据则抛出该异常。前两个异常的解决方法是首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对 方关闭连接后自己也要关闭该连接。

  • 相关阅读:
    ios 视频旋转---分解ZFPlayer
    IOS lame库 pcm转mp3 分析(方案二)
    IOS lame库 pcm转mp3 分析(方案一)
    ios 动态库合成包(真机&模拟器)脚本
    lame 制作ios静态库
    React Native scrollview 循环播放
    React Native Image多种加载图片方式
    汉字转拼音(包含多音字)
    React Native Alert、ActionSheet
    React Native Picker (城市选择器)
  • 原文地址:https://www.cnblogs.com/shirui/p/5269847.html
Copyright © 2011-2022 走看看