1. Socket 通信简介及模型
Java Socket 可实现客户端–服务器间的双向实时通信。
java.net包
中定义的两个类
socket和ServerSocket
,分别用来实现双向连接的client和server端。
1.1
重要的Socket API:
-
Accept
方法用于产生”阻塞”
,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续
-
GetInputStream
方法获得网络连接输入
,同时返回一个InputStream对象实例。
-
GetOutputStream
方法连接的另一端将得到输入
,同时返回一个OutputStream对象实例。
2. Socket 通信实现方法
2.1 服务器端(单线程)
- 实例化SeverSocket对象。
-
调用ServerSocket的accept()方法,生成socket对象,监听从端口上发来的连接请求,
等待连接期间会造成阻塞,
。 - 根据生成的客户端的Socket对象,进行读写IO操作。
- 关闭打开的流和Socket对象。
2.2 客户端
- 连接客户端指定IP端口,实例化socket对象。
- 根据生成socket对象,进行读写IO操作。
- 关闭打开的流和Socket对象。
2.3 服务器端 (多线程)
- 实例化SeverSocket对象,循环调用accept()等待客户端连接
- 客户端创建一个socket并请求和服务器端连接
- 服务器端接受客户端请求,创建socket与该客户建立专线连接
- 建立连接的两个socket在一个单独的线程上对话
- 服务器端继续等待新的连接
PS:多线程下服务器发送数据,客户端争抢服务器资源
服务器代码(单线程/单客户端)
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.PrintWriter;
import
java.net.ServerSocket;
import
java.net.Socket;
public
class
SocketService {
//搭建服务器端
public
static
void
main(String[] args)
throws
IOException{
SocketService socketService =
new
SocketService();
//1、a)创建一个服务器端Socket,即SocketService
socketService.oneServer();
}
public
void
oneServer(){
try
{
ServerSocket server=
null
;
try
{
server=
new
ServerSocket(3900);
//b)指定绑定的端口,并监听此端口。
System.
out
.println(
“服务器启动成功”
);
//创建一个ServerSocket在端口3900监听客户请求
}
catch
(Exception e) {
System.
out
.println(
“没有启动监听:”
+e);
//出错,打印出错信息
}
Socket socket=
null
;
try
{
socket=server.accept();
//2、调用accept()方法开始监听,等待客户端的连接
//使用accept()阻塞等待客户请求,有客户
//请求到来则产生一个Socket对象,并继续执行
}
catch
(Exception e) {
System.
out
.println(
“Error.”
+e);
//出错,打印出错信息
}
//3、获取输入流,并读取客户端信息
String line;
BufferedReader in=
new
BufferedReader(
new
InputStreamReader(socket.getInputStream()));
//由Socket对象得到输入流,并构造相应的BufferedReader对象
PrintWriter writer=
new
PrintWriter(socket.getOutputStream());
//由Socket对象得到输出流,并构造PrintWriter对象
BufferedReader br=
new
BufferedReader(
new
InputStreamReader(System.
in
));
//由系统标准输入设备构造BufferedReader对象
System.
out
.println(
“Client:”
+in.readLine());
//在标准输出上打印从客户端读入的字符串
line=br.readLine();
//从标准输入读入一字符串
//4、获取输出流,响应客户端的请求
while
(!line.equals(
“end”
)){
//如果该字符串为 “bye”,则停止循环
writer.println(line);
//向客户端输出该字符串
writer.flush();
//刷新输出流,使Client马上收到该字符串
System.
out
.println(
“Server:”
+line);
//在系统标准输出上打印读入的字符串
System.
out
.println(
“Client:”
+in.readLine());
//从Client读入一字符串,并打印到标准输出上
line=br.readLine();
//从系统标准输入读入一字符串
}
//继续循环
//5、关闭资源
writer.close();
//关闭Socket输出流
in.close();
//关闭Socket输入流
socket.close();
//关闭Socket
server.close();
//关闭ServerSocket
}
catch
(Exception e) {
//出错,打印出错信息
System.
out
.println(
“Error.”
+e);
}
}
}
客户端代码
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
java.io.PrintWriter;
import
java.net.InetAddress;
import
java.net.Socket;
import
java.net.URL;
public
class
SocketClient {
// 搭建客户端
public
static
void
main(String[] args)
throws
IOException {
try
{
// 1、创建客户端Socket,指定服务器地址和端口
Socket socket=
new
Socket(
“127.0.0.1”
,3900);
System.
out
.println(
“客户端启动成功”
);
// 2、获取输出流,向服务器端发送信息
// 向本机的3900端口发出客户请求
BufferedReader br =
new
BufferedReader(
new
InputStreamReader(System.
in
));
// 构造BufferedReader对象
PrintWriter write =
new
PrintWriter(socket.getOutputStream());
// 由Socket对象得到输出流,并构造PrintWriter对象
//3、获取输入流,并读取服务器端的响应信息
BufferedReader in =
new
BufferedReader(
new
InputStreamReader(socket.getInputStream()));
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
String readline;
readline = br.readLine();
// 从系统标准输入读入一字符串
while
(!readline.equals(
“end”
)) {
// 若从标准输入读入的字符串为 “end”则停止循环
write.println(readline);
// 将从系统标准输入读入的字符串输出到Server
write.flush();
// 刷新输出流,使Server马上收到该字符串
System.
out
.println(
“Client:”
+ readline);
// 在系统标准输出上打印读入的字符串
System.
out
.println(
“Server:”
+ in.readLine());
// 从Server读入一字符串,并打印到标准输出上
readline = br.readLine();
// 从系统标准输入读入一字符串
}
// 继续循环
//4、关闭资源
write.close();
// 关闭Socket输出流
in.close();
// 关闭Socket输入流
socket.close();
// 关闭Socket
}
catch
(Exception e) {
System.
out
.println(
“can not listen to:”
+ e);
// 出错,打印出错信息
}
}
}
服务器代码(多线程/多客户端)
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.PrintWriter;
import
java.net.ServerSocket;
import
java.net.Socket;
public
class
SocketService {
// 搭建服务器端
public
static
void
main(String[] args)
throws
IOException {
SocketService socketService =
new
SocketService();
// 1、a)创建一个服务器端Socket,即SocketService
socketService.oneServer();
}
public
void
oneServer() {
try
{
ServerSocket server =
null
;
try
{
server =
new
ServerSocket(3900);
// b)指定绑定的端口,并监听此端口。
System.
out
.println(
“服务器启动成功”
);
// 创建一个ServerSocket在端口3900监听客户请求
}
catch
(Exception e) {
System.
out
.println(
“没有启动监听:”
+ e);
// 出错,打印出错信息
}
Socket socket =
null
;
int
i = 0;
int
count = 100;
// 限制最大连接为100
while
(i++ < count) {
try
{
socket = server.accept();
System.
out
.println(
“当前连接数量:”
+ i);
// 2、调用accept()方法开始监听,等待客户端的连接
// 使用accept()阻塞等待客户请求,有客户
// 请求到来则产生一个Socket对象,并继续执行
Handler handler =
new
Handler(socket, i);
new
Thread(handler).start();
}
catch
(Exception e) {
System.
out
.println(
“Error.”
+ e);
// 出错,打印出错信息
}
}
server.close();
// 关闭ServerSocket
}
catch
(Exception e) {
// 出错,打印出错信息
System.
out
.println(
“Error.”
+ e);
}
}
}
class
Handler
implements
Runnable {
private
Socket
socket
;
private
int
i
;
public
Handler(Socket socket,
int
i) {
this
.
socket
= socket;
this
.
i
= i;
}
public
void
run() {
BufferedReader in =
null
;
PrintWriter writer =
null
;
BufferedReader br =
null
;
try
{
// 3、获取输入流,并读取客户端信息
String line;
in =
new
BufferedReader(
new
InputStreamReader(
socket
.getInputStream()));
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
writer =
new
PrintWriter(
socket
.getOutputStream());
// 由Socket对象得到输出流,并构造PrintWriter对象
br =
new
BufferedReader(
new
InputStreamReader(System.
in
));
// 由系统标准输入设备构造BufferedReader对象
System.
out
.println(
“Client:”
+
i
+
“:”
+ in.readLine());
// 在标准输出上打印从客户端读入的字符串
line = br.readLine();
// 从标准输入读入一字符串
// 4、获取输出流,响应客户端的请求
while
(!line.equals(
“end”
)) {
// 如果该字符串为 “bye”,则停止循环
writer.println(line);
// 向客户端输出该字符串
writer.flush();
// 刷新输出流,使Client马上收到该字符串
System.
out
.println(
“Server:”
+ line);
// 在系统标准输出上打印读入的字符串
System.
out
.println(
“Client”
+
i
+
“:”
+ in.readLine());
// 从Client读入一字符串,并打印到标准输出上
line = br.readLine();
// 从系统标准输入读入一字符串
}
// 继续循环
}
catch
(Exception e) {
System.
out
.println(
“Error.”
+ e);
// 出错,打印出错信息
}
finally
{
// 5、关闭资源
try
{
writer.close();
// 关闭Socket输出流
in.close();
socket
.close();
// 关闭Socket
}
catch
(IOException e) {
System.
out
.println(
“Error.”
+ e);
// 出错,打印出错信息
}
// 关闭Socket输入流
}
}
}
版权声明:本文为xhzhujin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。