文章目录
- 前言
- Socket类
2.1 Socket的通信过程
2.2 控制Socket连接
2.3 设置Socket的选项 - ServerSocket类
3.1 构造ServerSocket
3.2 ServerSocket的常用方法
3.3 设置ServerSocket选项 - 基于TCP的BIO通信
4.1 实现功能
4.2 程序源代码
4.3 程序效果截图
1. 前言
基于传输层协议TCP的网络通信是可靠的、有序的、差错控制的。TCP是面向连接的、可靠的流服务协议。TCP协议中,只有实现连接的双发才可以进行通信,因此广播和多播不是基于TCP的。下面首先介绍一些Socket和ServerSocket。
服务器、客户端建立通信的过程如下:
在这里插入图片描述
- 服务器网络接口的IP地址为10.1.1.1。服务器端应用程序在80端口运行服务,建立ServerSocket,并监听有无连接请求。
- 客户端必须知道服务器的IP地址或主机名、服务开放端口,客户端向服务器的服务Socket(10.1.1.1:80)发起请求。
- 服务器一旦接收该请求,就会在80端口上建立一个Socket,该Socket的本地地址为10.1.1.1:80,外部地址为客户端建立的Socket(client端IP地址,client端port)。客户端port通常由操作系统指定。
- 服务器每接收一个客户端的请求,就会在服务端口上建立一个Socket,这些Socket的本地地址相同,但外部地址各不相同。每个外部地址即各个客户端的本地Socket。这样服务器既可以监听服务请求,又可以和每个客户端进行独立的通信。
- 客户端通过本地Socket与服务器进行通信、读写信息。就像打电话一样,一个号码呼叫另一个号码,一旦被呼叫者接听,通信链路就建立起来了,双方就可以通话了。
2. Socket类
2.1 Socket的通信过程
在这里插入图片描述
2.2 控制Socket连接
获取Socket的输入流和输出流
服务端和客户端之间通信的Socket一旦连接,就会通过一对输入输出流进行通信。如同打电话时,一旦被叫放接听,双方通话的业务信道建立,就可以交流了。
Socket的getInputStream()方法和getOutputStream()方法分别实现获得输入流和输出流。
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader br = new BufferedReader(new IntputStreamReader(socket.getInputStream()));
获取Socket的地址端口信息
如果需要获得本地或者远程Socket的地址和端口信息,可以使用以下方法:
getInetAddress() //获得远程服务器的IP地址
getPort() //获得远程服务器的端口
getLocalAddress() //获得客户端本地的IP地址
getLocalPort() //获得客户端本地的端口
关闭Socket
当客户端与服务器的通信结束时,应该关闭Socket,以释放Socket占用的包括
InputStream和OutputStream在内的各种资源。
if(!s.isClosed()) s.close();
//判断如果不是空的话则关闭
Socket的状态
Socket类提供了3中方法(isBound 、isClosed 和 isConnected)来判断Socket的状态。
isBound方法用来判断Socket的绑定状态,只要曾经绑定过,即使Socket已经关闭,仍然返回true。可以理解为本地是否曾经建立过到远程主机的Socket连接。
isClosed方法用来判断Socket是否已经关闭。
isConnected方法用来判断Socket的连接状态。和isBound方法一样,即使Socket已经关闭,仍然返回true,isConnected的状态不清楚。可以理解为到远程主机的Socket是否曾经连接过。
3. 基于TCP的BIO通信
3.1 实现功能
服务器创建服务并监听端口,与客户端建立连接,并向客户端转发消息,客户端输入quit命令即可退出。
3.2 程序源代码
Server类:
package com.company.bio;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args){
final String QUIT = "quit";
final int DEFAULT_PORT = 8888;
ServerSocket serverSocket = null;
//绑定监听端口
try{
serverSocket = new ServerSocket(DEFAULT_PORT);
System.out.println("启动服务器,监听端口"+DEFAULT_PORT);
while (true){
// 等待客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端[" + socket.getPort() + "]已连接");
//创建IO流
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())
);
String msg = null;
while ((msg = bufferedReader.readLine()) != null) {
// 读取客户端发送的消息,当对方关闭时返回null
System.out.println("客户端["+socket.getPort()+"]:"+ msg);
//回复客户发送的消息
bufferedWriter.write("服务器:" + msg + "\n");
bufferedWriter.flush(); //保证缓冲区的数据发送出去
//查看客户端是否退出
if(QUIT.equals(msg)){
System.out.println("客户端["+socket.getPort()+"]已退出");
break;
}
}
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (serverSocket != null){
try {
serverSocket.close();
System.out.println("关闭ServerSocket");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Client类:
package com.company.bio;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
final String QUIT = "quit";
final String DEFAULT_SERVER_HOST = "127.0.0.1";
final int DEFAULT_SERVER_PORT = 8888;
Socket socket = null;
BufferedWriter bufferedWriter = null;
try{
// 创建socket
socket = new Socket(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT);
//创建IO流
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
bufferedWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())
);
//等待用户输入信息
BufferedReader consolReader = new BufferedReader(
new InputStreamReader(System.in)
);
while (true) {
String input = consolReader.readLine();
//发送消息给服务器
bufferedWriter.write(input + "\n");
bufferedWriter.flush();
//读取服务器返回的消息
String msg = bufferedReader.readLine();
System.out.println(msg);
//查看用户是否退出
if(QUIT.equals(input))break;
}
}catch (IOException e){
e.printStackTrace();
}finally {
if(bufferedWriter != null){
try {
bufferedWriter.close();
System.out.println("关闭socket");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.3 程序效果截图
Client:
在这里插入图片描述
Server:
在这里插入图片描述
更多资源和教程请关注公众号:非科班的科班。
如果觉得我写的还可以请给个赞,谢谢大家,你的鼓励是我创作的动力