三、Socket简解
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,他是一组接口,把复杂的TCP/IP协议族隐藏在Socket接口后面,用户使用Socket提供的接口即能实现连接远程机器-发送数据-接收数据-关闭连接-绑定端口-监听到达数据-在绑定的端口上接受来自远程机器的连接。Socket分为服务端ServerSocket和客户端Socket,建立连接时要分别创建对应的Socket实例。
客户端Socket构造方法说明:
Socket():创建一个新的未连接的Socket。
Socket(Proxy proxy):使用指定的代理类型创建一个新的未连接的Socket。
Socket(Sting dstName,int dstPort):使用指定的目标服务器IP地址和目标服务器端口号创建一个新的Socket。
Socket(Sting dstName,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的 Socket。
Socket(InetAddress localAddress,int localPort):使用指定的本地地址和本地端口,创建一个新的 Socket。
Socket(InetAddress dstAddress,int dstPort,InetAddress localAddress,int localPort):使用指定的目标主机、目标端口、本地地址和本地端口,创建一个新的 Socket。
其中,proxy为代理服务器地址,dstAddress为目标服务器IP地址,dstPort为目标服务器端口号,dstName为目标服务器主机名。
Socket client=new Socket("192.168.1.23", 2012);
// 第一个参数是目标服务器的 IP 地址,2012 是目标服务器的端口号
客户端Socket重要方法说明:
public InputStream getInputStream():读出该Socket中的数据。
public OutputStream getOutputStream():向Socke中写入数据。
public synchronized void close():关闭该Socket。
服务端ServiceSocket构造方法说明:
ServiceSocket():构造一个新的未绑定的ServiceSocket。
ServiceSocket(int port):构造一个新的ServiceSocket实例并绑定到指定端口,如果port为0,端口将由操作系统自动分配,此时进入队列的数目将被设置为50。
ServiceSocket(int port,int backlog):构造一个新的ServiceSocket实例并绑定到指定端口,并且指定进入队列的数目,如果port为0端口号由系统分配。
ServiceSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServiceSocket实例并绑定到指定端口和指定地址,同时指定进入队列的数目,如果localAddress为null,则可以使用任意地址,如果port为0端口由系统分配。
ServerSocket socketserver=new ServerSocket(2012);
// 2012 表示服务器要监听的端口号
服务端ServiceSocket重要方法说明:
public Socket accept():等待客户端Socket请求,直到链接被打开,该方法返回一个刚刚打开的连接的客户端Socket对象。
public void close():关闭服务器Socket。
Socket 一般有两种类型:TCP 套接字和 UDP 套接字。TCP 把消息分解成数据包并在接收端以正确的顺序把它们重新装配起来,TCP 还处理对遗失数据包的重传请求减少上层应用数据处理。UDP 不提供装配和重传请求这些功能,它只是向前传送信息包。上层的应用层必须确保消息是完整的,并且是以正确的顺序装配。
TCP服务端工作流程:
1,调用ServiceSocket(int port)创建一个ServiceSocket,并绑定到指定端口上。
2,调用accept(),监听连接请求,如果客户端请求连接则接受连接返回通信套接字。
3,调用Socket类的getOutputStream()和getInputStream()获取输出输入流开始网络数据的发送和接收。
4,调用close()方法关闭套接字。
// 创建一个 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,调用close()方法关闭套接字。
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();
}
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();
}
}