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

    说道网络编程,了解socket编程,分为TCP和UPD,对于具体实现细节,就不知道。希望学完这一块,自己能够独立完成一个socket的编写。

     关于互联网WEB相关的知识点,后面开始总结,今天不在此作介绍。

    Socket套接字:网络上具有唯一标识的IP地址和端口组合在一起才能构成唯一能识别的标识符套接字。

    Socket原理机制:

    通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。

    Java中的网络支持:针对网络通信的不同层次,Java提供了不同的API,其提供的网络功能有四大类:

    InetAddress:用于标识网络上的硬件资源,主要是IP地址

    URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。

    Sockets:使用TCP协议实现的网络通信Socket相关的类

    Datagram:使用UPD协议,将数据保存在用户数据中,通过网络进行通信。

    1:InetAddress

    标识网络上的硬件资源,没有构造方法(默认都没有),标识互联网协议IP地址

     1 package lesson1220Socket;
     2 
     3 import java.net.InetAddress;
     4 import java.net.UnknownHostException;
     5 
     6 public class InetAddressDemo {
     7 
     8     public static void main(String[] args) throws UnknownHostException {
     9         InetAddress address = InetAddress.getLocalHost();
    10         
    11         //InetAddress ad = new InetAddress();   The constructor InetAddress() is not visible
    12         
    13         byte [] by = address.getAddress();   //实际上里面存的值是[100, 98, 60, 87]       
    14         System.out.println(by);        
    15         System.out.println(address.getHostAddress());
    16         System.out.println(address.getHostName());
    17         return;        
    18     }
    19 }

    运行结果:

    [B@626287d3
    100.98.60.87
    CN00204505

    2、URL类

    统一资源定位符,标识Internet上某一资源的地址,

    Java中的网络编程

     Java中的网路编程主要是Java的Socket编程,属于JavaEE中的高级的部分,以下内容是对java网路编程的一个小结,代码都是经过编译调试的

      C/S程序应用:客户/服务器模式,如QQ客户端,客户端连到服务器上,一个C/S模式的应用必须有两套程序,一个是客户端的程序,一个是服务器程序。

      B/S程序应用:浏览器/服务器模式,如当下的各种网站都是B/S模式,所有的程序代码都在服务器上,用户通过浏览器去访问。

    C/S程序分为两种:

            基于TCP协议:Socket(套接字), 可靠的编程: A->B 如打电话先建立连接

            基于UDP协议:不可靠,如短信功能。

    如果编写一个TCP程序需要JAVA的两个包支持:

            java.net.*: 主要提供网络支持;

                    |-ServerSocket类:服务器端程序

                    |-Socket类:客户端程序

            java,io.*:传递信息流

    3、TCP编程

    TCP协议是面向连接的、可靠的、有序的、以字节流的方式发送数据。通过三次握手方式建立连接。形成传输数据的通道。在连接中进行大量数据的传输,效率会稍低。

    Java中基于TCP协议实现网络通信的类:客户端是Socket, 服务器端是ServerSocket。

     看上面图,可以看出Socket通信步骤:创建ServerSocket和Socket,打开连接到Socket的输入输出流,按照协议对Socket进行读写操作,关闭输入输出流,关闭Socket。

    3.1 服务器端:

    a:创建ServerScoket,并绑定端口

    b:调用accept()开始监听端口

    c:建立连接后,通过输入流获取客户端发送的请求信息

    d:通过输出流向客户端返回响应信息

    e:关闭Socket等相关资源

    3.2 客户端:

    a:创建Socket,并指定需要连接的服务器的IP和端口

    b:建立连接后,通过输出流向服务器端发送信息

    c:通过输入流获取服务器返回的响应信息

    d:关闭Socket等资源

    例子如下:

      1 package lesson1220Socket;
      2 
      3 import java.io.BufferedReader;
      4 import java.io.IOException;
      5 import java.io.InputStream;
      6 import java.io.InputStreamReader;
      7 import java.io.OutputStream;
      8 import java.io.PrintWriter;
      9 import java.net.ServerSocket;
     10 import java.net.Socket;
     11 
     12 import com.sun.org.apache.xalan.internal.xsltc.trax.OutputSettings;
     13 
     14 //基于TCP/IP协议的Socket,用户实现登录服务器端
     15 public class ServeSocketDemo {
     16     public static void main(String[] args) throws Exception {
     17         
     18         //1、创建一个ServerSocket服务端,指定绑定的端口,并监听端口
     19         ServerSocket ss = new ServerSocket(10086);   //1024-65535的某个值
     20         System.out.println("服务器端开始监听10086端口.....");
     21         //2、调用accept方法开始监听端口
     22         Socket socket = ss.accept();
     23         
     24         //3、获取输入流,并读取客户端信息
     25         InputStream is = socket.getInputStream();
     26         InputStreamReader isr = new InputStreamReader(is);   //InputStreamReader
     27         BufferedReader br = new BufferedReader(isr);
     28         
     29         String info = null;
     30         while((info = br.readLine())!=null){
     31             System.out.println("我是服务器,客户端说:"+info);            
     32         }
     33         socket.shutdownInput();
     34         
     35         //4、获取输出流,响应客户端请求
     36         OutputStream os = socket.getOutputStream();
     37         PrintWriter pw = new PrintWriter(os);
     38         pw.write("欢迎您");        
     39         pw.flush();
     40         System.out.println("给客户端回响应.....");
     41         
     42         //5、关闭资源
     43         pw.close();
     44         os.close();
     45         br.close();
     46         isr.close();
     47         is.close();
     48         socket.close();
     49         ss.close();
     50         
     51     }
     52 
     53 }
     54 
     55 
     56 package lesson1220Socket;
     57 
     58 import java.io.BufferedReader;
     59 import java.io.IOException;
     60 import java.io.InputStream;
     61 import java.io.InputStreamReader;
     62 import java.io.OutputStream;
     63 import java.io.PrintWriter;
     64 import java.net.Socket;
     65 import java.net.UnknownHostException;
     66 
     67 public class ClientSocketDemo {
     68 
     69     public static void main(String[] args) throws UnknownHostException, IOException {
     70         //1、创建客户端Socket,指定服务器和端口
     71         Socket cs = new Socket("127.0.0.1", 10086);
     72         System.out.println("与服务端建立连接.....");
     73         
     74         //2、获取输出流,向服务器发送信息
     75         OutputStream os = cs.getOutputStream();//直接输出流
     76         PrintWriter pw = new PrintWriter(os);
     77         pw.write("用户名:admin,密码:123");
     78         pw.flush();
     79         cs.shutdownOutput();
     80         System.out.println("向服务端发送信息.....");
     81         
     82         //3、获取输入流,得到服务器响应信息
     83         InputStream is = cs.getInputStream();
     84         InputStreamReader isr = new InputStreamReader(is);
     85         BufferedReader br = new BufferedReader(isr);
     86         String info;
     87         while((info = br.readLine())!=null){
     88             System.out.println("我是客户端,服务端响应信息:"+info);            
     89         }
     90         
     91         //4、关闭资源
     92         br.close();
     93         isr.close();
     94         is.close();
     95         pw.close();
     96         os.close();
     97         cs.close();            
     98 
     99     }
    100 
    101 }

    上面先运行服务端:ServeSocketDemo,再启动客户端:ClientSocketDemo

    运行结果如下:

    ServeSocketDemo:

    服务器端开始监听10086端口.....
    我是服务器,客户端说:用户名:admin,密码:123
    给客户端回响应.....
    ClientSocketDemo:

    与服务端建立连接.....
    向服务端发送信息.....
    我是客户端,服务端响应信息:欢迎您

    4、UDP编程

    前面介绍的Socket编程都是基于TCP/IP协议的,现在来看一下基于UDP协议编程。

    UPD协议(用户数据报协议)是无连接的、不可靠的、无序的,速度快。进行数据传输时,首先将要传输的数据定义成数据报(Datagram),大小限制在64k,在数据报中指明数据索要达到的Socket(主机地址和端口号),然后再将数据报发送出去。UDP协议的主要作用就是完成网络数据流和数据包之间的转换-------在信息发送端,UDP协议将网络数据流封装到数据报,然后被数据报发送出去;在信息接收端,UDP协议将数据报转换成实际数据内容。

    1>首先在UDP网络编程中没有服务器和客户端这种说法,两个Socket之间没有虚拟链路。只是接收和发送报文

    2>这里面有两个重要的类:DatagramSocket和DatagramPacket.

    DatagramSocket的两个构造函数:

    public DatagramSocket():构造数据报套接字并将其绑定到本地主机上任何可用的端口。

    public DatagramSocket(int port):创建数据报套接字并将其绑定到本地主机上的指定端口。

    在我们下面的DEMO中,UDPServerTest类中先发送数据报,使用的是套接字的无参构造器,而UDPClientTest类中先接收数据报,必须监听某一个端口,所以使用的是套接字的有参构造器。

    DatagramPacket的构造函数:

    public DatagramPacket(byte buf[], int length):用来接收长度为length的数据包

    public DatagramPacket(byte buf[], int length, InetAddress address, int port):用来将长度为length的包发送到指定主机上的指定端口号。

    package lesson1220Socket;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    
    public class UDPServer2 {
    
        public static void main(String[] args) throws Exception {
            DatagramSocket ds = new DatagramSocket();
            String str = "hello world";
            //构造用于发送的数据包,指定主机和端口号
            DatagramPacket packet = new DatagramPacket(str.getBytes(),
                    str.length(), InetAddress.getByName("localhost"), 5555);
            ds.send(packet);
            
            //读取从客户端发送过来的响应
            byte[] buffer = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(buffer,buffer.length);
            ds.receive(packet2);
            System.out.println("address: " + packet2.getAddress() + " port: "+ packet2.getPort());
            String str2 = new String(buffer,0,packet2.getLength());
            System.out.println(str2);
            ds.close();
        }
    
    }
    
    package lesson1220Socket;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class UDPClient2 {
    
        public static void main(String[] args) throws Exception {
            DatagramSocket ds = new DatagramSocket(5555);
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            ds.receive(packet);
            System.out.println("address: " + packet.getAddress() + " port: "+ packet.getPort());
            String str = new String(buffer, 0, packet.getLength());
            System.out.println(str);
    
            // 接收到数据包之后,客户端返回响应回去
            String str2 = "welcome";
            DatagramPacket packet2 = new DatagramPacket(str2.getBytes(), str2
                    .length(), packet.getAddress(), packet.getPort());
            ds.send(packet2);
            ds.close();
        }
    
    }

    上面的例子,要先运行UDPClient2(接收端先启动) ,然后再运行UDPServer2

    运行结果如下:

    UDPServer2

    address: /127.0.0.1 port: 5555
    welcome

    UDPClient2

    address: /127.0.0.1 port: 54071
    hello world

    1、上面的程序中,第一步是服务器端(暂且以这种叫法来区分这两个类)创建一个UDP套接字,没有指定端口,使用的是系统分配的端口。然后构建了一个数据包,包中指定      了目标机器的ip和端口号。

    2、作为客户端,创建了一个UDP套接字,并且绑定了端口,如果想要接收到服务端发送过来的报文,绑定的端口必须和服务器端发送的包中指定的端口一致。

    3、客户端打印了包中的内容之后,想要返回一些内容回去。这个时候,服务器端的ip和端口号可以从之前发送过来的数据包中获取。

         DatagramPacket packet2 = new DatagramPacket(str2.getBytes(), str2.length(), packet.getAddress(), packet.getPort());

    4、在服务器接收数据包的时候,已经不需要再像客户端创建套接字一样去绑定端口了,因为目前监听的端口和客户端发送的包中指定的端口是一样的。

    5、打印看下服务器端的ip和监听的端口号:(注意理解下这个地方端口号,不是5555)

    serverIp =/127.0.0.1;serverPort=54071

    6、其中DatagramSocket的receive(DatagramPacket p)方法在接收到数据包前一直阻塞。

    看下面这个例子:各自交互三次:

     1 package lesson1220Socket;
     2 
     3 import java.net.DatagramPacket;
     4 import java.net.DatagramSocket;
     5 import java.net.InetAddress;
     6 import java.net.SocketException;
     7 
     8 public class UDPServer {
     9 
    10     public static void main(String[] args) throws Exception {
    11         //1:创建服务器端Socket,指定端口
    12         DatagramSocket ds = new DatagramSocket(8888);
    13         //2、创建数据报,用于接收客户端发送的信息
    14         byte [] data = new byte[1024];        
    15         DatagramPacket dp = new DatagramPacket(data, data.length);
    16         //3、接收客户端发送的数据
    17         System.out.println("开始接收数据1111!");
    18         ds.receive(dp);        
    19         
    20         //4、读取数据
    21         String info = new String(data, 0, dp.getLength());
    22         System.out.println("我是服务端,收到客户端的信息是: "+info);
    23         
    24         
    25         //5、像客户端响应数据
    26         //定义客户端的地址、端口号和数据
    27         InetAddress ia = dp.getAddress();
    28         int port = dp.getPort();
    29         System.out.println("dp ia: " + ia + " port: " + port);
    30         //组装发送数据报
    31         byte []data2 = "你好客户端!".getBytes();
    32         DatagramPacket dp2 = new DatagramPacket(data2, data2.length, ia, port);        
    33         //响应客户端
    34         System.out.println("开始发送数据2222!");
    35         ds.send(dp2);
    36         
    37         
    38         //6、接收客户端第二次发送的数据
    39         System.out.println("开始接受数据3333!");
    40         ds.receive(dp);
    41         System.out.println("dp ia: " + dp.getAddress() + " port: " + dp.getPort());
    42         
    43         //7、读取数据
    44         info = new String(data, 0, dp.getLength());
    45         System.out.println("我是服务端,收到第二次客户端的信息是: "+info);
    46         
    47         
    48         ds.close();
    49     }
    50 
    51 }
    52 
    53 package lesson1220Socket;
    54 
    55 import java.io.IOException;
    56 import java.net.DatagramPacket;
    57 import java.net.DatagramSocket;
    58 import java.net.InetAddress;
    59 import java.net.SocketException;
    60 
    61 import sun.io.ByteToCharCp1006;
    62 
    63 public class UDPClient {
    64 
    65     public static void main(String[] args) throws Exception {
    66         
    67         InetAddress ia = InetAddress.getLocalHost();
    68         
    69         //1:创建客户端端Socket,指定端口和地址
    70         DatagramSocket ds = new DatagramSocket();
    71         //2、创建数据报,用于向服务器端发送信息
    72         byte [] data = "服务端你好".getBytes();        
    73         DatagramPacket dp = new DatagramPacket(data, data.length, ia, 8888);        
    74         //3、向服务器端发送数据
    75         System.out.println("A开始发送数据1111!");
    76         ds.send(dp);
    77         
    78         
    79         //4、读取数据
    80         byte [] data2 = new byte[1024];        
    81         DatagramPacket dp2 = new DatagramPacket(data2, data2.length);
    82         System.out.println("A开始接收数据2222!");
    83         ds.receive(dp2);
    84         
    85         System.out.println("dp2 ia: " + dp2.getAddress() + " port: " + dp2.getPort());
    86         String info = new String(data2, 0, dp2.getLength());
    87         System.out.println("我是客户端,服务器回的信息是: "+info);
    88        
    89         //5、第二次发送数据
    90         DatagramPacket dp3 = new DatagramPacket(data, data.length, dp2.getAddress(), dp2.getPort());    
    91         System.out.println("A开始发送数据3333!");
    92         ds.send(dp3);
    93         
    94         ds.close();
    95         
    96     }
    97 
    98 }

    上面这个程序先运行UDPServer, 再运行UDPClient。

    运行结果:

    UDPServer:

    开始接收数据1111!
    我是服务端,收到客户端的信息是: 服务端你好
    dp ia: /100.98.19.103 port: 56013
    开始发送数据2222!
    开始接受数据3333!
    dp ia: /100.98.19.103 port: 56013
    我是服务端,收到第二次客户端的信息是: 服务端你好

     UDPClient:

    A开始发送数据1111!
    A开始接收数据2222!
    dp2 ia: /100.98.19.103 port: 8888
    我是客户端,服务器回的信息是: 你好客户端!
    A开始发送数据3333!

    参考帖子:

    https://www.cnblogs.com/dongguacai/p/5747603.html

    https://www.cnblogs.com/dongguacai/p/5747397.html

     https://www.cnblogs.com/rocomp/p/4790340.html-------基础讲解

    https://www.cnblogs.com/Qian123/tag/java%E5%9F%BA%E7%A1%80/default.html?page=3

    https://www.cnblogs.com/yiwangzhibujian/p/7107785.html

    https://blog.csdn.net/facekbook/article/details/55506347

    其他基础:

    https://blog.csdn.net/hguisu/article/category/1122753

    https://www.cnblogs.com/dolphin0520/category/602384.html

    关于TCP/IP中更多的例子请看另一篇关于Socket多线程编程!

  • 相关阅读:
    Android Studio 字体和字号调整
    【IDEA】项目中引入Spring MVC
    【Double】double精度问题和int、long除不尽取舍问题
    【进制转换】原码反码和补码的理解以及进制转换
    【工具】SwitchHost的使用
    【工具】谷歌浏览器使用技巧
    【Git和GitHub】学习笔记
    【IE兼容性】代码中多语言样式+IE不兼容解决
    【Trello】使用指南
    【实操】进制转换:除基倒取余法
  • 原文地址:https://www.cnblogs.com/beilou310/p/10113928.html
Copyright © 2011-2022 走看看