本例实现了多客户端,当客户端a发送消息,按下回车后,所有的客户端均会收到a的消息。例子十分简单,做socket入门之用:
Myserver.java
package server;
import server.ServerThread;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Myserver {
//建立一个socket集合
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(30000);
//循环用于不断接收客户端连接
while(true){
Socket s = serverSocket.accept();
socketList.add(s);
//对于每一个客户端都启动一个新的线程
new Thread(new ServerThread(s)).start();
}
}
}
ServerThread.java
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread implements Runnable{
Socket socket = null;
//该线程所处理的Socket 所对应的输入流
BufferedReader br =null;
public ServerThread(Socket s) throws IOException{
this.socket= s;
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
public void run(){
try {
String content =null;
while((content = readFromClient())!=null){
for(Socket s:Myserver.socketList){
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(content);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String readFromClient() {
// TODO Auto-generated method stub
try {
return br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
Myserver.socketList.remove(socket);
}
return null;
}
}
刚刚开始接触socket对socket的getInputStream( )和getOutputStream( )方法不够理解,查资料后,解析如下:
socket的输入流和输出流
socket提供了InputStream getInputStream( );
OutputStream getOutputStream( ) l两个方法来获取输入流和输出流。
在理解这两个方法之前,首先要理解InputStream 和OutputStream
将流想象成管道,输入流是从别人创建的管道(如客户端创建的管道)里读数据
输出流则是向管道(自己的管道)中放数据
那么socket.getInputStream( )方法意为获取输入流,
SocketThread.java 部分代码解析
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
先将客户端发送的数据以字节流的形式从管道中读出,然后用它初始化一个字符流,再用这个字符流初始化一个字符缓冲流;
PrintStream ps = new PrintStream(s.getOutputStream());
意为获取将socket的输出流作为PrintStream的输出流
ps.println(content);
content 定义为从客户端读取的数据,用PrintStream 打印输出。
Myclient.java
package client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 30000);
//启动client 线程,不断读取来自服务器的消息
new Thread(new ClientThread(socket)).start();
//获取socket 对象对应的输出流
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
//不断从键盘读取输入
BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
while((line = bReader.readLine())!=null)
printStream.println(line);
}
}
ClientThread.java
package client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientThread implements Runnable {
private Socket socket;
private BufferedReader bf;
public ClientThread(Socket socket) throws IOException {
this.socket = socket;
// ??inputStreamReader
this.bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
String content = null;
while((content = bf.readLine())!=null)
System.out.println(content);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上代码均测试通过
下一篇将会详细剖析 InputStream 、 InputStreamReader和BufferedReader