其实
简单的分析一下
就可以看出客户和服务通讯的主要通道就是Socket本身
而服务器通过accept方法就是同意和客户建立通讯
这样当客户建立Socket的同时
服务器也会使用这一根连线来先后通讯
那么既然如此只要我们存在多条连线就可以了
那么我们的程序可以变为如下:
服务器:
import javaio*;
import *;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket();
while(true){
Socket client=serveraccept();
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
PrintWriter out=new PrintWriter(clientgetOutputStream());
while(true){
String str=inreadLine();
Systemoutprintln(str);
outprintln(has receive);
outflush();
if(strequals(end))
break;
}
clientclose();
}
}
}
这里仅仅只是加了一个外层的While循环这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互这里也就是接受到客户的End消息那么现在就实现了多客户之间的交互了但是问题又来了这样做虽然解决了多客户可是是排队执行的也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互无法做到同时服务那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了所以线程是最好的解决方案
那么下面的问题是如何使用线程首先要做的事情是创建线程并使得其可以和网络连线取得联系然后由线程来执行刚才的操作要创建线程要么直接继承Thread要么实现Runnable接口要建立和Socket的联系只要传递引用就可以了而要执行线程就必须重写run方法而run方法所做的事情就是刚才单线程版本main所做的事情因此我们的程序变成了这样:
import *;
import javaio*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
thisclient=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
PrintWriter out=new PrintWriter(clientgetOutputStream());
//Mutil User but can parallel
while(true){
String str=inreadLine();
Systemoutprintln(str);
outprintln(has receive);
outflush();
if(strequals(end))
break;
}
clientclose();
}catch(IOException ex){
}finally{
}
}
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket();
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(serveraccept());
mustart();
}
}
}
我的类直接从Thread类继承了下来并且通过构造函数传递引用和客户Socket建立了联系这样每个线程就有了一个通讯管道同样我们可以填写run方法把之前的操作交给线程来完成这样多客户并行的Socket就建立起来了
以上的代码使用的是
BufferedReader in=new BufferedReader(new InputStreamReader(clientgetInputStream()));
PrintWriter out=new PrintWriter(clientgetOutputStream());
还有一种方法是使用
DataInputStream isFromClient = new DataInputStream(clientgetInputStream());
DataOutputStream osToClient = new DataOutputStream(clientgetOutputStream());
关于这两种输入输出流的不同我也只知道前一种对字符串支持比较好后面对于读取一个字符串需要处理但是可以支持很多种类型的输出对于传递字符串而言前一种应该是很好的选择了