相比前面一个例子,这里加入了多线程的操作,服务器可以不断读取客户端数据,并向客户端写入数据;客户端也可以不断的读取服务器数据,并向服务器写入数据。支持多客户端,功能实际就是一个基于Socket的TCP简易聊天程序,服务端实现了消息的转发。
局域网中电脑A用作服务端,IP为192.168,31.168
同时电脑A中开启另一个终端作为一个客户端
电脑B用作客户端,IP为192.168.31.132
TCP服务端:
package cn.com.tcpthread;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class TcpServer_2 {
//定义保存所有Socket的ArrayList
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(30001);
while(true)
{
//此行代码会阻塞,将一直等待别人的连接
Socket s = ss.accept();
socketList.add(s);
//每当客户端连接后,启动一条ServerThread线程为该客户端服务
new Thread(new ServerThread(s)).start();
}
}
}
TCP服务端线程实现:
package cn.com.tcpthread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread implements Runnable{
//定义当前线程所处理的Scoket
Socket s = null;
//该线程所处理的Socket所对应的输入流
BufferedReader br = null;
//String line=null;
public ServerThread(Socket s) throws IOException {
this.s = s;
//初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run() {
try
{
String connect = null;
//采用循环不断从Socket中读取客户端送过来的数据
while((connect = readFromClient()) != null)
{
//遍历socketList中的每个Socket,将读到的内容向每个Socket发送一次
for(Socket s: TcpServer_2.socketList)
{
//输出流
PrintStream ps = new PrintStream(s.getOutputStream());
System.out.println(connect);
ps.println(connect);
//不断读取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//line=null;
//ps.println(connect);
while((connect=br.readLine()) != null)
{
//将用户的键盘输入内容写入Socket对应的输出流
ps.println(connect);
//break;
//System.out.println(connect);
}
//break;
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
//定义读取客户端数据的方法
private String readFromClient()
{
try
{
return br.readLine();
}
//如果捕捉到异常,表明该Socket对应的客户端已经关闭
catch(IOException e)
{
//删除该Socket
TcpServer_2.socketList.remove(s);
}
return null;
}
}
TCP客户端:
package cn.com.tcpthread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient_2 {
/**
* 客户端
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.1.101", 30001);
//客户端启动ClientThread线程不断读取来自服务器的数据
new Thread(new ClientThread(s)).start();
//获取该Socket对应的输出流
PrintStream ps = new PrintStream(s.getOutputStream());
//ps.print("123123123");
String line = null;
//不断读取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while((line=br.readLine()) != null)
{
//将用户的键盘输入内容写入Socket对应的输出流
ps.println(line);
}
}
}
TCP客户端线程:
package cn.com.tcpthread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientThread implements Runnable
{
//该线程负责处理的Socket
private Socket s;
//该线程所处理的Socket所对应的输入流
BufferedReader br = null;
public ClientThread(Socket s)throws IOException
{
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run()
{
try
{
String connect = null;
//不断读取Socket输入流中的内容,并将这些内容打印输出
while((connect = br.readLine()) != null)
{
System.out.println(connect);
}
}catch(Exception e)
{
e.printStackTrace();
}
}
}