基于Socket编程的网络聊天室
程序员文章站
2022-06-30 19:15:34
...
1.项目简介:
基于Socket编程的网络聊天室
2.功能描述:
可以实施多个用户的注册,群发和私聊:
3.具体实现流程:
客户端实现流程:
1.客户端的功能可以进一步细化为:
对外发送信息:
接受其他客户端的信息:
由于发送和接受的功能应该是独立的,所以使用两个线程来分别实现:
1.发送线程:
内部主要实现原理是通过获取sokcet输出流,通过输出流发送信息
2.如果有Bye字样则关闭Socket退出聊天
public class Write implements Runnable{
private Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
//获取输出流
PrintStream out=new PrintStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
String msg=null;
while(true) {
if(scanner.hasNext()) {
msg = scanner.next();
}
out.println(msg);
if(msg.contains("Bye")){
socket.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
接受其他客户端的信息:
流程:
获取输入流来读取从服务器发送的信息:
class Read implements Runnable{
private Socket socket;
public Read(Socket socket) {
this.socket = socket;
}
public void run() {
Scanner scanner= null;
try {
scanner = new Scanner(socket.getInputStream());
while(true){
System.out.println("等待客户端发来的消息");
String str=null;
if(scanner.hasNext()){
System.out.println(scanner.next());
}
if(socket.isClosed()){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器实现流程:
一个中转站的功能:将发送来的信息进行分类,来达到注册、群发、私聊的功能
public class Services {
private static Map<String,Socket> map=new ConcurrentHashMap<String, Socket>();
static private class RealServices implements Runnable{
private Socket socket;
public RealServices(Socket socket) {
this.socket = socket;
}
public void run() {
try {
Scanner in=new Scanner(socket.getInputStream());
String msg=null;
while(true){
if(in.hasNext()) {
msg = in.next();
}
Pattern pattern = Pattern.compile("\r");
java.util.regex.Matcher matcher = pattern.matcher(msg);
//如果以userName开头则是注册,即将所有用户信息存放在map中
if(msg.startsWith("userName")){
String username=msg.split(":")[1];
register(username);
continue;
}
//G开头说明是群聊
if(msg.startsWith("G")){
String send=msg.split(":")[1];
group(send);
}
//收到数据已P开头说明是私聊
if (msg.startsWith("P")){
String username=msg.split(":")[1].split("\\-")[0];
String send=msg.split("\\-")[1];
privateSend(username,send);
}
if(msg.contains("Bye")){
Set<Map.Entry<String, Socket>> entries = map.entrySet();
Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
String username=null;
Socket socket=null;
while(iterator.hasNext()){
Map.Entry<String,Socket> i=iterator.next();
username=i.getKey();
socket=i.getValue();
if(socket==this.socket){
iterator.remove();
}
}
group(username+"退出群聊,当前聊天室还剩"+map.size());
System.out.println(username+"退出群聊");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void register(String username) throws IOException {
if(map.containsKey(username)){
System.out.println("当前用户已存在");
}else {
map.put(username,socket);
group("欢迎"+username+"加入聊天室,当前聊天室人数:"+map.size());
System.out.println("欢迎"+username+"加入聊天室,当前聊天室人数:"+map.size());
}
}
//遍历map集合将每一个数据发送出去
private void group(String send) throws IOException {
Set<Map.Entry<String, Socket>> entries = map.entrySet();
Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
while (iterator.hasNext()){
Map.Entry<String,Socket> i=iterator.next();
Socket socket=i.getValue();
if(socket==this.socket){
continue;
}
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println(send);
}
}
//私聊获取指定用户的Socket,创建连接发送
private void privateSend(String username, String send) throws IOException {
Socket to=map.get(username);
if(to==null){
PrintStream out=new PrintStream(socket.getOutputStream());
out.println("当前用户不存在");
}else {
PrintStream out=new PrintStream(to.getOutputStream());
out.println("发送信息: "+send);
}
}
}
上一篇: js中不同的暴露和引入文件的方式
下一篇: 前端开发之js基础(2)