Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个针对TCP和UDP编程的接口(API),通过Socket,我们才能使用TCP/IP协议。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口。
一.利用Socket建立网络连接的步骤
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1。服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2。客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3。连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
二.Socket 一般有两种类型:TCP 套接字和 UDP 套接字
1.使用 TCP 通信
TCP 服务器端工作的主要步骤如下:
步骤 1 调用 ServerSocket(int port)创建一个 ServerSocket,并绑定到指定端口上。
步骤 2 调用 accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字。
步骤 3 调 用 Socket 类 的 getOutputStream() 和 getInputStream() 获 取 输 出 和 输 入 流,开始网络数据的发送和接收。
步骤 4 关闭通信套接字。
// 创建一个 ServerSocket 对象
ServerSocket serverSocket = null;
try {
// TCP_SERVER_PORT 为指定的绑定端口,为 int 类型
serverSocket = new ServerSocket(TCP_SERVER_PORT);
// 监听连接请求
Socket socket = serverSocket.accept();
// 写入读 Buffer 中
BufferedReader in = new BufferedReader(new
// 获取输入流
InputStreamReader(socket.getInputStream()));
// 放到写 Buffer 中
BufferedWriter out = new BufferedWriter(new
// 获取输出流
OutputStreamWriter(socket.getOutputStream()));
// 读取接收信息,转换为字符串
String incomingMsg = in.readLine() + System.getProperty("line.separator");
// 生成发送字符串
String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT +
System.getProperty("line.separator");
// 将发送字符串写入上面定义的 BufferedWriter 中
out.write(outgoingMsg);
// 刷新,发送
out.flush();
// 关闭
socket.close();
} catch (InterruptedIOException e) {
// 超时错误
e.printStackTrace();
// IO 异常
} catch (IOException e) {
// 打印错误
e.printStackTrace();
} finally {
// 判定是否初始化 ServerSocket 对象,如果初始化则关闭 serverSocket
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP 客户端工作的主要步骤如下:
步骤 1 调用 Socket() 创建一个流套接字,并连接到服务器端。
步骤 2 调 用 Socket 类 的 getOutputStream() 和 getInputStream() 方 法 获 取 输 出 和 输 入流,开始网络数据的发送和接收。
步骤 3 关闭通信套接字。
try {
// 初始化 Socket,TCP_SERVER_PORT 为指定的端口,int 类型
Socket socket = new Socket("localhost", TCP_SERVER_PORT);
// 获取输入流
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
// 生成输出流
BufferedWriter out = new BufferedWriter(new
OutputStreamWriter(socket.getOutputStream()));
// 生成输出内容
String outMsg = "TCP connecting to " + TCP_SERVER_PORT +
System.getProperty("line.separator");
// 写入
out.write(outMsg);
// 刷新,发送
out.flush();
// 获取输入流
String inMsg = in.readLine() + System.getProperty("line.separator");
Log.i("TcpClient", "received: " + inMsg);
// 关闭连接
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
2.使用 UDP 通信
UDP 服务器端工作的主要步骤如下:
步骤 1 调用 DatagramSocket(int port) 创建一个数据报套接字,并绑定到指定端口上。
步骤 2 调用 DatagramPacket(byte[]buf,int length),建立一个字节数组以接收 UDP 包。
步骤 3 调用 DatagramSocket 类的 receive(),接受 UDP 包。
步骤 4 关闭数据报套接字。
// 接收的字节大小,客户端发送的数据不能超过 MAX_UDP_DATAGRAM_LEN
byte[] lMsg = new byte[MAX_UDP_DATAGRAM_LEN];
// 实例化一个 DatagramPacket 类
DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
// 新建一个 DatagramSocket 类
DatagramSocket ds = null;
try {
// UDP 服务器监听的端口
ds = new DatagramSocket(UDP_SERVER_PORT);
// 准备接收数据
ds.receive(dp);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 如果 ds 对象不为空,则关闭 ds 对象
if (ds != null) {
ds.close();
}
}
UDP 客户端工作的主要步骤如下:
步骤 1 调用 DatagramSocket() 创建一个数据包套接字。
步骤 2 调用 DatagramPacket(byte[]buf,int offset,int length,InetAddress address,int port),建立要发送的 UDP 包。
步骤 3 调用 DatagramSocket 类的 send() 发送 UDP 包。
步骤 4 关闭数据报套接字。
// 定义需要发送的信息
String udpMsg = "hello world from UDP client " + UDP_SERVER_PORT;
// 新建一个 DatagramSocket 对象
DatagramSocket ds = null;
try {
// 初始化 DatagramSocket 对象
ds = new DatagramSocket();
// 初始化 InetAddress 对象
InetAddress serverAddr = InetAddress.getByName("127.0.0.1");
DatagramPacket dp;
// 初始化 DatagramPacket 对象
dp = new Datagram
Packet(udpMsg.getBytes(), udpMsg.length(), serverAddr, UDP_SERVER_PORT);
// 发送
ds.send(dp);
// 异常处理
// Socket 连接异常
}catch (SocketException e) {
e.printStackTrace();
// 不能连接到主机
}catch (UnknownHostException e) {
e.printStackTrace();
// 数据流异常
} catch (IOException e) {
e.printStackTrace();
// 其他异常
} catch (Exception e) {
e.printStackTrace();
} finally {
// 如果 DatagramSocket 已经实例化,则需要将其关闭
if (ds != null) {
ds.close();
}
}