zoukankan      html  css  js  c++  java
  • Java Socket

      Java最初是作为网络编程语言出现的,Java Socket可以实现网络上两个程序之间的数据交换,QQ等即时通讯软件都使用了Socket相关技术。Java.net包中提供了网络编程相关的四大功能类:InetAddress、URL、Sockets、Datagram。

    一、InetAddress

       InetAddress类用于标识网络上的硬件资源,标识互联网协议(IP)地址。 该类没有构造方法

    //获取本机的InetAddress实例
    InetAddress address =InetAddress.getLocalHost();
    address.getHostName();//获取计算机名
    address.getHostAddress();//获取IP地址
    byte[] bytes = address.getAddress();//获取字节数组形式的IP地址,以点分隔的四部分
    
    //获取其他主机的InetAddress实例
    InetAddress address2 =InetAddress.getByName("其他主机名");
    InetAddress address3 =InetAddress.getByName("IP地址");

    二、URL

      1. URL(Uniform Resource Locator)统一资源定位符,表示Internet上某一资源的地址,协议名:资源名称       

    //创建一个URL的实例
    URL baidu =new URL("http://www.baidu.com");
    URL url =new URL(baidu,"/index.html?username=tom#test");//?表示参数,#表示锚点
    url.getProtocol();//获取协议
    url.getHost();//获取主机
    url.getPort();//如果没有指定端口号,根据协议不同使用默认端口。此时getPort()方法的返回值为 -1
    url.getPath();//获取文件路径
    url.getFile();//文件名,包括文件路径+参数
    url.getRef();//相对路径,就是锚点,即#号后面的内容
    url.getQuery();//查询字符串,即参数

      2.  使用URL读取网页内容

    通过URL对象的openStream()方法可以得到指定资源的输入流,通过流能够读取或访问网页上的资源      
    //使用URL读取网页内容
    //创建一个URL实例
    URL url =new URL("http://www.baidu.com");
    InputStream is = url.openStream();//通过openStream方法获取资源的字节输入流
    InputStreamReader isr =newInputStreamReader(is,"UTF-8");//将字节输入流转换为字符输入流,如果不指定编码,中文可能会出现乱码
    BufferedReader br =newBufferedReader(isr);//为字符输入流添加缓冲,提高读取效率
    String data = br.readLine();//读取数据
    while(data!=null){
        System.out.println(data);//输出数据
        data = br.readerLine();
    }
    br.close();
    isr.colose();
    is.close();

    三、TCP编程

      TCP(Transfer Control Protocol,传输控制协议)也叫流通信协议,该协议是面向连接的、可靠的、有序的、以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道。TCP是一种可靠的协议,接收端收到的包的顺序和包在发送端的顺序是一致的,所有的数据会按照接受时的顺序读取。在连接中进行大量数据的传输,效率会稍低。

           Java中基于TCP协议实现网络通信的类有Socket类(客户端)和 ServerSocket类(服务器端)

    1. 服务器端实现步骤

      ① 创建ServerSocket对象,绑定监听端口
      ② 通过accept()方法监听客户端请求
      ③ 连接建立后,通过输入流读取客户端发送的请求信息
      ④ 通过输出流向客户端发送相应信息
      ⑤ 关闭相关资源
    public class TCPServer {
        public static final int PORT = 8897; // 0~1023这些端口都已经被系统预留了,选择端口时应大于1023。
        
        public static void main(String[] args) throws IOException {
            new TCPServer().work();
        }
    
        public void work() throws IOException {
            ServerSocket 
            ss = new ServerSocket(PORT);
            while(true) { // 使用死循环以便一直监听某端口是否有连接请求
                Socket socket = ss.accept();
                new WorkThread(socket); // 使用多线程处理客户端请求
            }    
        }
        
        private class WorkThread implements Runnable {
            Socket socket;
            public WorkThread(Socket socket) {
                this.socket = socket;
                new Thread(this).start(); // 启动线程
            }
            
            @Override
            public void run() {
                try {
                    byte[] buf = new byte[1024];
                    OutputStream os = socket.getOutputStream();
                    InputStream is = socket.getInputStream();
                    StringBuilder builder = new StringBuilder();
                    is.read(buf); // 读数据
                    System.out.println("Message From Client:" + new String(buf));
                    os.write("This is Server".getBytes()); // 写数据
                    socket.close();
                    os.close();    
                    is.close();
                    socket.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }    
        }
    }
     
    2. 客户端实现步骤
      ① 创建Socket对象,指明需要连接的服务器的地址和端口号
      ② 连接建立后,通过输出流想服务器端发送请求信息
      ③ 通过输入流获取服务器响应的信息
      ④ 关闭响应资源 
    public class TCPClient {
        public static final int PORT = 8897;
        
        public static void main(String[] args) throws IOException {
            byte[] buf = new byte[1024];
            Socket socket = new Socket("127.0.0.1", PORT);
            OutputStream os = socket.getOutputStream();
            InputStream is = socket.getInputStream();
            os.write("This is Client".getBytes()); // 写数据
            is.read(buf); // 读数据
            System.out.println("Message From Server:" + new String(buf));
            socket.close();
            os.close();    
            is.close();
        }
    }

    四、UDP编程

      UDP协议(用户数据报协议)是无连接的、不可靠的、无序的,速度快。与TCP不同,UDP每次发送数据报时,需要附带上本机的socket描述符和接收端的socket描述符。进行数据传输时,首先将要传输的数据定义成数据报(Datagram),大小限制在64k,在数据报中指明数据索要达到的Socket(主机地址和端口号),然后再将数据报发送出去。UDP是一种不可靠的协议,发送的数据报不一定会按照其发送顺序被接收端的socket接受。

         Java中基于UDP协议实现网络通信的类有 DatagramPacket类(表示数据报包) 和 DatagramSocket类(进行端到端通信的类)。

    服务器端:

    public class UDPServer {
        public static int PORT = 9987;
        
        public static void main(String[] args) throws IOException {
            InetAddress address = InetAddress.getLocalHost();
            DatagramSocket socket = new DatagramSocket(PORT, address);
            
            // 接收数据
            byte[] buf = new byte[1024];
            DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
            socket.receive(recvPacket);
            String message = new String(buf, 0, recvPacket.getLength());
            System.out.println("Message From Client: " + message);
                    
            // 发送数据
            byte[] data = "This is Server".getBytes();
            SocketAddress socketAdderss = recvPacket.getSocketAddress();
            DatagramPacket packet = new DatagramPacket(data, data.length, socketAdderss); // 使用接收包的socketAdderss
            socket.send(packet);    
            socket.close();
        }
    }

    客户端:

    public class UDPClient {
        public static int PORT = 9987;
        
        public static void main(String[] args) throws IOException {
            DatagramSocket socket = new DatagramSocket();
            
            // 发送数据
            byte[] data = "This is Client".getBytes();
            InetAddress address = InetAddress.getLocalHost();
            DatagramPacket packet = new DatagramPacket(data, data.length, address, PORT);
            socket.send(packet);
            
            // 接收数据
            byte[] buf = new byte[1024];
            DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
            socket.receive(recvPacket);
            String message = new String(buf, 0, recvPacket.getLength());
            System.out.println("Message From Server: " + message);
            socket.close();
        }
    }

      运行程序时先跑服务器端代码,服务器端会阻塞在receive方法上,等待客户端发送消息后才能继续往下跑。同样,客户端的receive方法也会在收到服务器端的消息后才会往下执行。

     
    参考文章: http://www.cnblogs.com/rocomp/p/4790340.html
  • 相关阅读:
    如何在ubuntu里面使用JNI?
    sql server 关键字一
    自己编写的 objectDataSource 配合 GridView 实现分页...
    委托和匿名委托的比较
    实现 IEnumerable IEnumator 接口的类,可直接用作 Gridivew 的数据源
    ASP.NET 中的页面事件执行顺序
    泛型,集合的根本区别
    匿名委托的示例,贴一下以供参考...
    ajax "Sys 未定义" 的问题解决方法
    抽象工厂模式(C#)
  • 原文地址:https://www.cnblogs.com/anxiao/p/6867467.html
Copyright © 2011-2022 走看看