IP 地址 + 端口号组成了 Socket,Socket 是网络上运行的程序之间双向通信链路的终点, 是 TCP 和 UDP 的基础, 网络通信其实就是 Socket 间的通信, 数据在两个 Socket 间通过 IO 传输
InetAddress
用于标识网络上的硬件资源
- // 获取本机的 InetAddress 实例
- InetAddress address = InetAddress.getLocalHost();
- // 获取计算机名
- address.getHostName();
- // 获取 IP 地址
- address.getHostAddress();
- // 获取字节数组形式的 IP 地址, 以点分隔的四部分
- byte[] bytes = address.getAddress();
- // 获取其他主机的 InetAddress 实例
- InetAddress address3 = InetAddress.getByName("127.0.0.1");
- URL
统一资源定位符, 通过 URL 可以直接读取或写入网络的数据资源
- // 创建一个 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(); // 查询字符串, 即参数
通过 URL 对象的 openStream() 方法可以得到指定资源的输入流, 通过流能够读取或访问网页上的资源
- URL baidu = new URL("http://www.baidu.com");
- InputStream is = baidu.openStream();
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String content = null;
- while ((content = br.readLine()) != null) {
- System.out.println(content);
- }
- br.close();
- is.close();
TCP 编程
TCP 协议是面向连接可靠的有序的以字节流的方式发送数据, 基于 TCP 协议实现的网络通信, 通信模型流程如下
TCP 通信流程
客户端 Socket
客户端的 Socket 类, 需指明要连接的服务器地址和端口号, 建立连接后通过输入输出流发送和响应信息
- public class Client {
- public static void main(String[] args) {
- try (Socket socket = new Socket("127.0.0.1",8999)){
- // 像服务器端发送信息
- OutputStream os = socket.getOutputStream();
- PrintWriter pw = new PrintWriter(os);
- pw.write("我是客户端 linyuan");
- pw.flush();
- // 接收服务器端消息
- InputStream is = socket.getInputStream();
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String message = null;
- while ((message = br.readLine()) != null) {
- System.out.println("服务器说:" + message);
- }
- // 关闭资源.....
- pw.close();
- os.close();
- is.close();
- br.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
服务器端 ServerSocket
创建服务器端 ServerSocket 并绑定端口, 通过 accept() 方法监听客户端请求, 建立连接后通过输入输出流发送和响应信息
- public class Server {
- public static void main(String[] args) {
- try (ServerSocket serverSocket = new ServerSocket(8999)) {
- System.out.println("服务器启动................");
- while (true) {
- // 监听客户端连接
- Socket socket = serverSocket.accept();
- // 接收客户端消息
- InputStream is = socket.getInputStream();
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String message;
- while ((message = br.readLine()) != null) {
- System.out.println("客户端说:" + message);
- }
- // 向客户端发送消息
- OutputStream os = socket.getOutputStream();
- PrintWriter pw = new PrintWriter(os);
- pw.write("欢迎加入 xxx 服务器.........");
- pw.flush();
- // 关闭资源.....
- br.close();
- is.close();
- pw.close();
- os.close();
- socket.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
UDP 编程
UDP 协议 (用户数据报协议) 是无连接的不可靠的无序的, 速度快
进行数据传输时, 首先将要传输的数据定义成数据报(DatagramPacket), 大小限制在 64k, 并指名要发送的地址 Socket(主机地址和端口号), 然后再将数据报发送出去
服务器端实现
创建 DatagramSocket 并绑定端口, 创建 DatagramPacket 并调用 receive 方法接收客户端发送的数据报(该方法会阻塞到接收到数据报为止), 读取数据
- public class Server {
- public static void main(String[] args) {
- try{
- byte[] data = new byte[1024];
- // 接收客户端数据报
- DatagramSocket socket = new DatagramSocket(10000);
- DatagramPacket rPacket = new DatagramPacket(data,0,data.length);
- socket.receive(rPacket);
- String info = new String(data,0,rPacket.getLength());
- System.out.println("客户端发送内容:"+info);
- // 响应客户端
- InetSocketAddress socketAddress = new InetSocketAddress(rPacket.getAddress(),rPacket.getPort());
- data = "新的一天!".getBytes();
- DatagramPacket sPacket = new DatagramPacket(data,0,data.length,socketAddress);
- socket.send(sPacket);
- socket.close();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
客户端实现
定义要发送的消息, 创建 DatagramPacket, 通过 DatagramSocket 发送数据
- public class Client {
- public static void main(String[] args) {
- try{
- InetSocketAddress socketAddress = new InetSocketAddress("localhost",10000);
- byte[] data = "我是客户端".getBytes();
- DatagramPacket packet = new DatagramPacket(data,0,data.length,socketAddress);
- DatagramSocket socket = new DatagramSocket();
- socket.send(packet);
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
来源: http://www.jianshu.com/p/6ca1c102fc00