简要介绍
本例子中主要有四个类,Server类主要是等待客户端连接,和读取客户端发来的数据,并可以通过键盘向客户端发送消息,ServerThread类是在Server中调用的,它是一个线程,主要是实现服务端从键盘读取数据的功能,这里为什么要新建一个线程来读数据,因为BufferedReader的readLine()方法读取数据时,在该方法成功返回之前,线程被阻塞,程序无法再执行下去,所以要想输入数据必须新开线程。同样在Client中从服务端的输入流读数据也是在一个新的线程中。最好将下面四个类放在一个包下。
1、Server类
<pre name="code" class="java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(3000);
// 该缓冲流用于从客户端读入数据
BufferedReader read = null;
String str = null;
while(true){
// 服务器收到客户端的Socket请求时,服务端也创建一个Socket,如何没有客户端请求,该方法一直处于阻塞状态
Socket s = ss.accept();
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 该线程用于从键盘读取数据,并将数据写入Socket的输出流中
new Thread(new ServerThread(s)).start();
while((str = read.readLine())!=null){
System.out.println(str);
}
}
}
}
2、ServerThread类
<pre name="code" class="java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
/**
*该线程用于从键盘读取数据,并将数据写入Socket的输出流中
* @author 王维
*
*/
public class ServerThread implements Runnable {
Socket s;
// 用于将数据写入Socket中的输出流
PrintStream ps;
// 从键盘中读取输入的内容
BufferedReader reader;
public ServerThread(Socket s){
this.s = s;
reader = new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void run() {
String str = null;
try {
ps = new PrintStream(s.getOutputStream());
while((str = reader.readLine()) != null){
ps.println(str+" (from Server)");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3、Client类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException{
// 创建本机连接,端口号3000
Socket socket = new Socket("127.0.0.1", 3000);
// 该流用于读取服务器发来的数据
PrintStream ps = new PrintStream(socket.getOutputStream());
String str = null;
// 该流用于读取键盘的输入内容
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// 该线程用于从服务器中读入数据
new Thread(new ClientThread(socket)).start();
// 从键盘中读取数据
while((str = reader.readLine()) != null){
ps.println(str+" (from Client)");
}
reader.close();
socket.close();
}
}
4、ClientThread类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 该线程用于从服务器中读入数据
* @author 王维
*
*/
public class ClientThread implements Runnable{
Socket s;
BufferedReader read;
public ClientThread(Socket s){
this.s = s;
try {
// 从服务器中读取内容
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String str = null;
try {
while((str = read.readLine()) != null){
System.out.println(str);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}