综述
Java为TCP提供了用于客户端的Socket类,和用于服务器端的ServerSocket类,为什么要学习这个东西?平时用的东西都被tomcat等服务器封装了,而看不到底层的信息,课堂上老师要求基于socket来编写c/s架构的分布式系统,以了解一下服务器底层的实现细节。因此,本篇文章用来总结一下TCP Socket的一些基本的使用方法与搭建细节。
Socket
Socket类是Java执行客户端TCP操作的基础类
Socket类为程序提供的接口是流,对Socekt数据的实际读写是通过流类来进行的。
public Socket(String host, int port)
public Socket(InetAddress host, int port)
ServerSocket
服务器程序的基本生命周期:
1. new ServerSocket()
2. ServerSocekt使用accept()方法监听此端口的入站连接。accept()会一直阻塞,直到客户端尝试进行连接,此时accept()会返回一个连接客户端和服务器的Socket对象。
3. 根据服务器类型,会调用Socket的getInputStream()方法或getOutputStream()方法,以获得与客户端通信的输入和输出流
4. 关闭连接
建立一个服务器进程需要五个步骤:
1. 建立ServerSocket对象
ServerSocket server = new ServerSocket(PORT_NUMBER);
//服务器将会在端口号PORT_NUMBER中监听来自客户端的连接
2. 使服务器进入等待状态
Socket link = server.accept();
//当连接建立后,返回一个Socket对象
3. 设置输入输出流
Scanner input = new Scanner(link.getInputStream());
//使用Scanner包装InputStream对象,以得到面向字符串的输入
PrintWriter output = new PrintWriter(link.getOutputStream(),true);
//true表示自动刷新
4. 收发数据
output.println("Awating data...");
String input = input.nextLine();
5. 关闭连接
link.close();
建立一个客户端进程需要四个步骤:
1. 建立与服务器间的连接
Socket(IP_ADDRESS,PORT_NUMBER)
Socket link = new Socket(InetAddress.getLocalHost(),1234);
2. 建立输入输出流
3. 输入输出数据
4. 关闭连接
下面写一个最基本的Server,用来接收客户端的一条信息,并向客户端发送一条信息。
public class ServerDemo {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(8189);
/*
* 服务器等待客户端的请求,若收到请求则返回一个Socket对象
* 用于封装客户端请求
*/
Socket link = server.accept();
/*
* 下面两个方法分别用于得到Socket对象的输入流对象和输出流对象
* 向输出流写内容,另一端可以通过输入流读取
*/
InputStream is = link.getInputStream();
OutputStream os = link.getOutputStream();
/*
* 服务器端向输出流对象写入“hello,well”
* 客户端可以使用输入流对象读取这些内容
*/
os.write("hello, well".getBytes());
byte buf[] = new byte[1024];
/*
* 读取客户端发送过来的输入流对象
* 并将其保存到buf数组中
*/
int len = is.read(buf);
System.out.println(new String(buf,0,len));
is.close();
os.close();
link.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
一个最基本的客户端Socket,用于向服务器发送一条消息,并接收一条回应信息。
public class BasicClient{
public static final int MYPORT = 8188;
public static void main(String[] args){
Socket server = null;
InetAddress address = null;
try {
address = InetAddress.getByName("localhost");
server = new Socket(address, MYPORT);
/*
* 使用BufferedReader类来包装输入流,可以使服务器一行一行的来接收数据
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(
server.getInputStream()));
PrintStream writer = new PrintStream(server.getOutputStream());
// 客户端向输出流写入数据
// 服务器可以通过输入流读取这些数据
writer.println("Hello server! - from client");
// 服务器向输出流写入的数据
// 客户端通过输入流读出,并将其保存在字符串serverMessage中
String serverMessage = reader.readLine();
System.out.println(serverMessage);
server.close();
} catch(Exception e) {
e.printStackTrace();
}
}
} // BasicClient
最后,可以使用线程来实现同步的问题,以使服务器能够接受多个客户端的请求。