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
posted @ 2017-05-17 14:38  安小  阅读(298)  评论(0编辑  收藏  举报