前两天想到一个手机APP项目,使用到蓝牙,发现BluetoothSocket和J2EE网络变成的Socket差不多,使用之余顺手写一个多线程服务器与客户端交互实现聊天室的一个小例子,方便新人学习网络编程模块,期间使用到多线程和IO输入输出流的操作,有点儿不明白的过后我会有一些个人使用心得总结,敬请期待哈!
源码内容十分简单,我工程文件我存在下面的地址上去了,方便大家下载,0积分,为了方便大家学习了。
Server.Java文件,主要是服务端管理,通过多线程接收各用户发送消息以及消息转送等处理。
package cn.com.dnyy.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Server {
// 用以存放客户端Socket的管理Map集合
private Map<String, ClientManager> ClientManagers = null;
public static void main(String[] args) {
new Server().startServer();// 启动服务端
}
// 开启服务器方法
private void startServer(){
ServerSocket ss = null;// 服务器Socket
Socket s = null;// 与客户端交互的Socket
try {
ss = new ServerSocket(8888);// 创建服务器,端口为8888
ClientManagers = new HashMap<String, Server.ClientManager>();// 创建管理集合
System.out.println("创建服务器成功!");
while(true){
s = ss.accept();// 接收客户端请求Socket管道
ClientManager cm = new ClientManager(s);// 新建线程Runnable
new Thread(cm).start();// 构建新线程管理该客户端Socket
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(ss != null) ss.close();// 关闭服务器
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 管理客户端Socket线程内部类
private class ClientManager implements Runnable {
private Socket clientSocket;// 客户端Socket
private BufferedReader br;// 基于客户端Socket的输入流(从客户端输入服务端)
private PrintWriter pw;// 基于客户端Socket的输出流(服务端输出到客户端)
private boolean flag;// 线程可用标识
private String physicalAddress;// 客户端名
private String userName;// 用户名
// 构造方法
public ClientManager(Socket s) throws IOException{
this.clientSocket = s;// 获取客户端Socket
br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 基于客户端Socket创建输入流
pw = new PrintWriter(s.getOutputStream(), true);// 基于客户端Socket创建输出流
physicalAddress = s.getInetAddress().getHostAddress()+":"+s.getPort();// 获取客户端Socket物理地址:端口
userName = br.readLine();// 获取用户名
flag = true;// 标识可用
System.out.println(userName+"["+physicalAddress+"]"+"已经成功连接到服务器!");// 客户端连接服务器成功消息发送给所有在线用户
sendMessageForAll("已经成功连接到服务器!");// 客户端连接服务器成功消息发送给所有在线用户
ClientManagers.put(userName, this);// 将自身加入全局客户端线程管理中
sendOnlineList(false);// 发送当前所有在线用户的列表
}
/*
* 发送当前所有在线用户的列表
* 参数IsOnly-->true:发送给当前用户;false:发送给所有在线用户;
*/
private void sendOnlineList(boolean IsOnly) {
if(IsOnly){
StringBuilder sb = new StringBuilder(KeyWords.ONLINE_CLIENTS_LIST + "所有人");// 在线用户列表前缀
for(Map.Entry<String, ClientManager> item : ClientManagers.entrySet()){
// 遍历在线用户Socket集合
if(userName.equals(item.getKey())) continue;// 不加入自身
sb.append(",&#