Socket
1 什么是Socket
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
但是,Socket所支持的协议种类也不光TCP/IP、UDP,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
socket连接就是所谓的长连接,客户端和服务器需要互相连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉的,但是有时候网络波动还是有可能的
Socket偏向于底层。一般很少直接使用Socket来编程,框架底层使用Socket比较多,
2 socket属于网络的那个层面

- Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个外观模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
3 Socket通讯的过程
- 基于TCP:服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
- 基于UDP:UDP 协议是用户数据报协议的简称,也用于网络数据的传输。虽然 UDP 协议是一种不太可靠的协议,但有时在需要较快地接收数据并且可以忍受较小错误的情况下,UDP 就会表现出更大的优势。我客户端只需要发送,服务端能不能接收的到我不管
4 TCP协议Socket代码示例:
先运行服务端,在运行客户端
- 服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.test.io;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
public class BIOServer { public static void main(String[] args) { ServerSocket server = null; Socket socket = null; InputStream in = null; OutputStream out = null; try { server = new ServerSocket(8000); System.out.println("服务端启动成功,监听端口为8000,等待客户端连接..."); while (true){ socket = server.accept(); System.out.println("客户连接成功,客户信息为:" + socket.getRemoteSocketAddress()); in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = in.read(buffer)) > 0) { System.out.println(new String(buffer, 0, len)); } out = socket.getOutputStream(); out.write("hello!".getBytes()); } } catch (IOException e) { e.printStackTrace(); } } }
|
- 客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.test.io;
import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner;
public class Client01 { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 8000); OutputStream outputStream = socket.getOutputStream(); System.out.println("TCP连接成功 \n请输入:"); while(true){ byte[] car = new Scanner(System.in).nextLine().getBytes(); outputStream.write(car); System.out.println("TCP协议的Socket发送成功"); outputStream.flush(); } } }
|
先运行服务端,在运行客户端。测试结果发送成功:

·

5 UDP协议Socket代码示例:
- 服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Server1 { public static void main(String[] args) { try { DatagramSocket socket = new DatagramSocket(8888); byte[] car = new byte[1024]; DatagramPacket packet = new DatagramPacket(car, car.length); System.out.println("等待UDP协议传输数据"); socket.receive(packet); int length = packet.getLength(); System.out.println("啥东西来了:" + new String(car, 0, length)); socket.close(); System.out.println("UDP协议Socket接受成功"); } catch (IOException e) { e.printStackTrace(); } } }
|
- 客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Client1 { public static void main(String[] args) { try { DatagramSocket socket = new DatagramSocket(2468); byte[] car = "UDP协议的Socket请求,有可能失败哟".getBytes(); InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888); DatagramPacket packet = new DatagramPacket(car, car.length, address); socket.send(packet); System.out.println("UDP协议的Socket发送成功"); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
|
先运行服务端,在运行客户端。测试结果成功发送成功:

6 Socket的常用类
| 类名 |
用于 |
作用 |
| Socket |
TCP协议 |
Socket类同时工作于客户端和服务端,所有方法都是通用的,这个类三个主要作用,校验包信息,发起连接(Client),操作流数据(Client/Server) |
| ServerSocket |
TCP协议 |
ServerSocket表示为服务端,主要作用就是绑定并监听一个服务器端口,为每个建立连接的客户端“克隆/映射”一个Socket对象,具体数据操作都是通过这个Socket对象完成的,ServerSocket只关注如何和客户端建立连接 |
| DatagramSocket |
UDP协议 |
DatagramSocket 类用于表示发送和接收数据报包的套接字。 |
| DatagramPacket |
UDP协议 |
DatagramPacket 类用来表示数据报包,数据报包用来实现无连接包投递服务。 |
| InetAddress |
IP+端口号 |
Java提供了InetAddress类来代表互联网协议(IP)地址,InetAddress类没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例: |
| InetSocketAddress |
IP+端口号 |
在使用Socket来连接服务器时最简单的方式就是直接使用IP和端口,但Socket类中并未提供这种方式,而是靠SocketAddress的子类InetSocketAddress来实现 IP 地址 + 端口号的创建,不依赖任何协议。 |