多线程与网络编程(BIO处理模型)
现在虽然已经实现了一个标准的网络程序开发,但是在整个的开发过程之中本程序存在有严重的性能缺陷,因为该服务器只能为一个线程提供Echo服务,如果现在的服务器需要有多人进行连接访问的时候,那么其他的使用者将无法连接(等待连接)。
所以现在就可以发现单线程的服务器开发本身就是一种不合理的做法,那么此时最好的解决方案就是将每一个连接到服务器上的客户端都通过一个线程对象来进行处理,即:服务器上启动多个线程,每一个线程单独为每一个客户端实现Echo服务支持。
范例:修改服务器端程序
服务器端
package EchoModel.Server;
import javax.swing.plaf.TableHeaderUI;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Locale;
import java.util.Scanner;
public class EchoServer {
private static class ClientThread implements Runnable{
private Socket client = null; //描述每一个不同的客户端
private Scanner scanner = null;
private PrintStream out = null;
private boolean flag = true;
public ClientThread(Socket client) throws IOException {
this.client = client;
//首先需要接受客户端接受来的信息,而后已才可以将信息处理之后发送回客户端
this.scanner = new Scanner(this.client.getInputStream()); //接收客户端输入内容
scanner.useDelimiter("\n");//设置分隔符
this.out = new PrintStream(this.client.getOutputStream()); //向客户端输出内容
}
@Override
public void run() {
while (flag){
if(scanner.hasNext()){//有数据发送
String value = scanner.next().trim();//接收发送的内容,除去字符串开头和末尾的空格或其他字符
if("byebye".equalsIgnoreCase(value)){
out.println("ByeByeBye...");
this.flag = false; //结束循环
}else{
out.println("【ECHO】"+value);
}
}
}
try {
scanner.close();
out.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1010); //设置服务器端口的监听端口
System.out.println("等待客户端连接......");
boolean flag = true;
while (flag){
Socket client = serverSocket.accept(); //循环接收客户端
new Thread(new ClientThread(client)).start(); //线程启动
}
}
}
客户端
package EchoModel.client;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class EchoClient {
private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost",1010); //定义服务端的连接信息
//现在的客户端需要有输入与输出支持,所以依然要准备Scanner与PrintWriter
Scanner scanner = new Scanner(socket.getInputStream()); //接收服务器端的输入内容
scanner.useDelimiter("\n");//设置分隔符
PrintStream out = new PrintStream(socket.getOutputStream()); //向服务器端发送内容
boolean flag = true;
while (flag){
String input = getString("请输入要发送的内容").trim(); //除去字符串开头和末尾的空格或其他字符
out.println(input); //要加换行,因为换行是分隔符
if(scanner.hasNext()){ //服务器回应了
System.out.println(scanner.next());
}
if("byebye".equalsIgnoreCase(input)){
flag = false;
}
}
out.close();
scanner.close();
socket.close();
}
public static String getString(String prompt) throws IOException {
System.out.println(prompt);
String str = KEYBOARD_INPUT.readLine(); //读取键盘输入数据
return str;
}
}
如果在这类的代码里面再追加一些集合的数据控制,实际上就可以实现一个80年代的聊天室。