传统Socket编程的回顾(一)

来源:互联网 发布:移动网络营业 编辑:程序博客网 时间:2024/05/29 19:23

1、服务端

import java.net.ServerSocket;import java.net.Socket;public class Server {public void listener(int port) {ServerSocket server = null;try {server = new ServerSocket(port);System.out.println("server start  port " + port + " ... ");// 进行阻塞,用于接收客户端的请求while (true) {Socket socket = server.accept();// 新建一个线程执行客户端的任务new Thread(new ServerHandler(socket)).start();}} catch (Exception e) {e.printStackTrace();}}// 开启服务器public static void main(String[] args) {new Server().listener(8338);}}

2、服务端的handler,用于处理客户端的请求

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class ServerHandler implements Runnable {private Socket socket;private BufferedReader reader;private PrintWriter writer;public ServerHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 模拟线程池处理不及时reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));writer = new PrintWriter(this.socket.getOutputStream(), true);// 用于处理客户端的请求,并返回信息给客户端while (true) {handle(reader, writer);}} catch (Exception e) {e.printStackTrace();} finally {// 释放资源CloseUtils.closeCloseable(reader, writer, socket);}}// 用于获取客户端的请求信息// 并将返回信息,发送给客户端private void handle(BufferedReader reader, PrintWriter writer) {String requestInfo = null;try {// 用于接收客户端的请求信息requestInfo = reader.readLine();// 如果有信息,就进行读取操作// 如果为null,就关闭socket连接,释放资源if (requestInfo != null) {// 打印查看,responseInfo信息System.out.println("Server: from client data is: "+ requestInfo);// 根据客户端的请求数据,服务端进行处理// getAnswer(String question),就是根据客户端的请求// 获取相应的数据信息(比如查询数据库)String resposeInfo = getAnswer(requestInfo);// 服务端,根据客户端的请求数据,返回的数据sendDataToClient(writer, resposeInfo);}} catch (IOException e) {// e.printStackTrace();// 释放资源CloseUtils.closeCloseable(reader, writer, socket);return;}}// 服务端,用于给客户端发送数据// 也就是将,根据客户端的请求的信息,获取的返回信息。返回给客户端// 客户端,给服务端发送请求数据private static void sendDataToClient(PrintWriter writer, String responseInfo) {writer.println(responseInfo);// 服务端写数据给客户端的时候,要执行flush()操作// 不然客户端,可能不会及时的接收到信息writer.flush();}// 根据用户的请求,获取返回信息// 实际的开发,可以到数据库获取数据private String getAnswer(String question) {String answer = "请输入 who, 或者what, 或者where";if ("who".equals(question)) {answer = "我是莉莉";} else if ("what".equals(question)) {answer = "我是来帮你解闷的";} else if ("where".equals(question)) {answer = "我来自外太空";} else {answer = "请输入 who, 或者what, 或者where";}// 实际开发,可以根据请求信息// 到数据库查询数据,并且返回给客户端System.out.println(answer);return answer;}}

3、关闭Closeable接口的工具类

import java.io.Closeable;import java.io.IOException;public class CloseUtils {public static void closeCloseable(Closeable... closeables) {for (int i = 0; i < closeables.length; i++) {if (closeables[i] != null) {try {closeables[i].close();} catch (IOException e) {e.printStackTrace();}}}}}

4、客户端代码

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;import java.util.Scanner;public class Client {private String ADDRESS = null;private int PORT;private Socket socket = null;private BufferedReader in = null;private PrintWriter out = null;public void connect(String address, int port) {try {this.ADDRESS = address;this.PORT = port;socket = new Socket(ADDRESS, PORT);in = new BufferedReader(new InputStreamReader(socket.getInputStream()));out = new PrintWriter(socket.getOutputStream(), true);// 客户端向服务端,发送数据// 同时接受,服务端响应的信息while (true) {// 1.接受客户端控制台的输入,并发送给服务端// 以方法的形式抽离出去了Scanner scanner = new Scanner(System.in);String requestInfo = scanner.nextLine();sendDataToServer(out, requestInfo);// 2.接受服务端响应的数据,并处理// 因为处理,根据不同的业务,处理不同// 所以抽离出去,使用handleResponse(String response)函数处理// 在这里,只是简单的输出打印handleResponse(in);}} catch (Exception e) {e.printStackTrace();} finally {CloseUtils.closeCloseable(in, out, socket);}}// 客户端,给服务端发送请求数据private static void sendDataToServer(PrintWriter writer, String requestInfo) {writer.println(requestInfo);}// 对服务端返回的数据,做处理// 这可以是一个逻辑,所有从上面的代码抽出来// 是的代码,看起来更加的整洁美观private static void handleResponse(BufferedReader reader) {String response;try {response = reader.readLine();System.out.println("Client接收到Server发来的数据: " + response);} catch (IOException e) {throw new RuntimeException(e);}}// 测试方法public static void main(String[] args) {new Client().connect("127.0.0.1", 8338);}}

5、程序测试

       

6、关于客户端关闭后,服务端出现java.net.SocketException: Connection reset 的异常信息

      6.1  异常的信息

java.net.SocketException: Connection resetat java.net.SocketInputStream.read(SocketInputStream.java:135)at java.net.SocketInputStream.read(SocketInputStream.java:122)at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)at java.io.InputStreamReader.read(InputStreamReader.java:184)at java.io.BufferedReader.fill(BufferedReader.java:154)at java.io.BufferedReader.readLine(BufferedReader.java:317)at java.io.BufferedReader.readLine(BufferedReader.java:382)at bhz.bio.ServerHandler.handle(ServerHandler.java:44)at bhz.bio.ServerHandler.run(ServerHandler.java:28)at java.lang.Thread.run(Thread.java:745)

      6.2  异常产生的原因

              在服务端的处理器ServerHandler.java中,在读取客户端发来的信息的时候,requestInfo = reader.readLine();用于接收客户端,发来的信息。当客户端突然断开连接的时候,这个read()方法,就会抛出一个异常信息。所以只要捕获这个异常信息,并和之前关闭的客户端关联的Socket连接就好了。

      6.3  解决的方法



1 0
原创粉丝点击