第四次过程性考核
码云地址:https://gitee.com/snjsnjsnj/events
心得:
1:Socket的传输模式
Socket有两种主要的操作方式:面向连接的和无连接的。(TCP/UDP)
面向连接的Socket操作就像一部电话,Socket必须在发送数据之前与目的地的Socket取得连接,一旦连接建立了,Socket就可以使用一个流接口进行打开、读写以及关闭操作。并且,所有发送的数据在另一端都会以相同的顺序被接收。
无连接的Socket操作就像一个邮件投递,每一个数据报都是一个独立的单元,它包含了这次投递的所有信息(目的地址和要发送的内容)。在这个模式下的Socket不需要连接目的地Socket,它只是简单的投出数据报。
由此可见,无连接的操作是快速高效的,但是数据安全性不佳;面向连接的操作效率较低,但数据的安全性较好。
本文主要介绍的是面向连接的Socket操作:
2:
Socket的构造方法
Java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的Socket客户端和服务器端。
Socket的构造方法如下:
(1)Socket(InetAddress address, int port);
(2)Socket(InetAddress address, int port, boolean stream);
(3)Socket(String host, int port);
(4)Socket(String host, int port, boolean stream);
(5)Socket(SocketImpl impl);
(6)Socket(String host, int port, InetAddress localAddr, int localPort);
(7)Socket(InetAddress address, int port, InetAddrss localAddr, int localPort);
ServerSocket的构造方法如下:
(1)ServerSocket(int port);
(2)ServerSocket(int port, int backlog);
(3)ServerSocket(int port, int backlog, InetAddress bindAddr);
服务器端创建了一个ServerSocket:
try {
ServerSocket serverSocket = new ServerSocket(50000); //创建一个ServerSocket,用于监听客户端Socket的连接请求
while(true) {
Socket socket = serverSocket.accept(); //每当接收到客户端的Socket请求,服务器端也相应的创建一个Socket
//todo开始进行Socket通信
}catch (IOException e) {
e.printStackTrace();
}
客户端创建并启动一个Socket:
try {
socket = new Socket("192.168.1.101", 50000); //192.168.1.101是服务器的IP地址,50000是端口号
//todo开始进行Socket通信
} catch (IOException e) {
e.printStackTrace();
}
服务器端ServerSocket的实现:
/*
* Class : MyServer类,用于监听客户端Socket连接请求
* Author : 博客园-snj流沙
*/
public class MyServer {
//定义ServerSocket的端口号
private static final int SOCKET_PORT = 50000;
//使用ArrayList存储所有的Socket
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public void initMyServer() {
try {
//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket serverSocket = new ServerSocket(SOCKET_PORT);
while(true) {
//每当接收到客户端的Socket请求,服务器端也相应的创建一个Socket
Socket socket = serverSocket.accept();
socketList.add(socket);
//每连接一个客户端,启动一个ServerThread线程为该客户端服务
new Thread(new ServerThread(socket)).start();
}
}catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyServer myServer = new MyServer();
myServer.initMyServer();
}
}
ServerThread类的具体实现如下:
public class ServerThread implements Runnable {
//定义当前线程所处理的Socket
private Socket socket = null;
//该线程所处理的Socket对应的输入流
private BufferedReader bufferedReader = null;
/*
* Function : ServerThread的构造方法
* Author : 博客园-snj流沙
*/
public ServerThread(Socket socket) throws IOException {
this.socket = socket;
//获取该socket对应的输入流
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
/*
* Function : 实现run()方法,将读到的客户端内容进行广播
* Author : 博客园-snj流沙
*/
public void run() {
try {
String content = null;
//采用循环不断地从Socket中读取客户端发送过来的数据
while((content = bufferedReader.readLine()) != null) {
//将读到的内容向每个Socket发送一次
for(Socket socket : MyServer.socketList) {
//获取该socket对应的输出流
PrintStream printStream = new PrintStream(socket.getOutputStream());
//向该输出流中写入要广播的内容
printStream.println(packMessage(content));
}
e.printStackTrace();
}
}
/*
* Function : 对要广播的数据进行包装
* Author : 博客园-snj流沙
*/
private String packMessage(String content) {
String result = null;
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); //设置日期格式
if(content.startsWith("USER_ONE")) {
String message = content.substring(8); //获取用户发送的真实的信息
result = "\n" + "往事如风 " + df.format(new Date()) + "\n" + message;
}
if(content.startsWith("USER_TWO")) {
String message = content.substring(8); //获取用户发送的真实的信息
result = "\n" + "依旧淡然 " + df.format(new Date()) + "\n" + message;
}
return result;
}
}
客户端Socket的实现:
/*
* Function : 初始化Socket
* Author : 博客园-snj流沙
*/
private void initSocket() {
try {
socketUser1 = new Socket(URL_PATH, SOCKET_PORT); //用户1的客户端Socket
socketUser2 = new Socket(URL_PATH, SOCKET_PORT); //用户2的客户端Socket
clientThread = new ClientThread(); //客户端启动ClientThread线程,读取来自服务器的数据
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
ClientThread的具体实现:
/*
* Function : run()方法,用于读取来自服务器的数据
* Author : 博客园-snj流沙
*/
public void run() {
try {
String content = null;
while((content = bufferedReader .readLine()) != null) {
Bundle bundle = new Bundle();
bundle.putString(KEY_CONTENT, content);
Message msg = new Message();
msg.setData(bundle); //将数据封装到Message对象中
myHandler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
创建一个内部类MyHandler,让它继承Handler类,并实现handleMessage()方法:
/*
* Class : 内部类MyHandler,用于接收消息并处理
* Author : 博客园-snj流沙
*/
private class MyHandler extends Handler {
public void handleMessage(Message msg) {
Bundle bundle = msg.getData(); //获取Message中发送过来的数据
String content = bundle.getString(KEY_CONTENT);
MyContent.setContent(content); //保存聊天记录
mTextView.setText(MyContent.getContent());
}
}
浙公网安备 33010602011771号