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读取网页内容 //创建一个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是一种可靠的协议,接收端收到的包的顺序和包在发送端的顺序是一致的,所有的数据会按照接受时的顺序读取。在连接中进行大量数据的传输,效率会稍低。
1. 服务器端实现步骤
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(); } } } }
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方法也会在收到服务器端的消息后才会往下执行。