基于Java的Socket多客户端Client-Server聊天程序的实现
任务要求
编写一个简单的Socket多客户端聊天程序:
- 客户端程序,从控制台输入字符串,发送到服务器端,并将服务器返回的信息显示出来
- 服务器端程序,从客户机接收数据并打印,同时将从标准输入获取的信息发送给客户机
- 满足一个服务器可以服务多个客户
低配版本链接
实现代码
工具类
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;
importjava.net.Socket;
publicclassSocketUtils{
publicstaticvoidwriteToSocket(Socketsocket,Stringmessage)throwsIOException{
writeToOutputStream(socket.getOutputStream(),message);
}
publicstaticvoidwriteToDataOutputStream(DataOutputStreamdos,Stringmessage)throwsIOException{
dos.writeUTF(message);
dos.flush();
}
publicstaticvoidwriteToOutputStream(OutputStreamos,Stringmessage)throwsIOException{
writeToDataOutputStream(newDataOutputStream(os),message);
}
}
服务器端线程
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjava.util.Map;
publicclassChatServerRunnableimplementsRunnable{
privateSocketsocket;
privateDataOutputStreamdos;
privateDataInputStreamdis;
privateStringcurrentUserNickName;
publicChatServerRunnable(Socketsocket)throwsIOException{
this.socket=socket;
this.dos=newDataOutputStream(socket.getOutputStream());
this.dis=newDataInputStream(socket.getInputStream());
}
@Override
publicvoidrun(){
try{
write("欢迎来到聊天室!");
login();
System.out.println(currentUserNickName+"用户登录成功");
write(currentUserNickName+",您已登录。\n输入【listusers】可以查看当前登录用户列表\n输入【toall消息内容】可以群发消息\n输入【to某个用户消息内容】可以给指定用户发送消息\n输入【exit】可以退出聊天");
Stringinput=dis.readUTF();
while(!ChatServer.EXIT.equals(input)){
System.out.println(currentUserNickName+"输入了"+input);
if(input.startsWith("to")){
sendMessage(input);
}elseif("listusers".equals(input)){
showOnlineUsers();
}else{
write("您输入的命令不合法,请重新输入!");
}
input=dis.readUTF();
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
ChatServer.nickNameSocketMap.remove(currentUserNickName);
try{
dis.close();
}catch(IOExceptione){
e.printStackTrace();
}
try{
dos.close();
}catch(IOExceptione){
e.printStackTrace();
}
try{
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
privatevoidlogin()throwsIOException{
write("请输入你的昵称:");
while(true){
StringnickName=dis.readUTF();
System.out.println("用户输入了昵称:"+nickName);
synchronized(ChatServerRunnable.class){
if(!ChatServer.nickNameSocketMap.containsKey(nickName)){
currentUserNickName=nickName;
ChatServer.nickNameSocketMap.put(nickName,socket);
break;
}else{
write("您输入的昵称已存在,请重新输入:");
}
}
}
}
privatevoidsendMessage(Stringinput)throwsIOException{
intreceiverEndIndex=input.indexOf("",3);
Stringreceiver=input.substring(3,receiverEndIndex);
Stringmessage=input.substring(receiverEndIndex+1);
if("all".equals(receiver)){
broadcast(message);
}else{
sendIndividualMessage(receiver,message);
}
}
privatevoidsendIndividualMessage(Stringreceiver,StringorignalMessage)throwsIOException{
SocketreceiverSocket=ChatServer.nickNameSocketMap.get(receiver);
if(receiverSocket!=null){
SocketUtils.writeToSocket(receiverSocket,formatMessage("你",orignalMessage));
}else{
write("您要单独聊天的用户【"+receiver+"】不存在或者已经下线");
}
}
privateStringformatMessage(Stringreceiver,StringoriginalMessage){
StringBuildermessageBuilder=newStringBuilder();
messageBuilder.append(currentUserNickName).append("对").append(receiver).append("说:\n")
.append(originalMessage).append("\n发送时间:")
.append(newSimpleDateFormat("yyyy-MM-ddHH:mm:ss").format(newDate()));
returnmessageBuilder.toString();
}
privatevoidbroadcast(StringorignalMessage)throwsIOException{
for(Map.Entryentry:ChatServer.nickNameSocketMap.entrySet()){
if(!currentUserNickName.equals(entry.getKey())){
SocketUtils.writeToSocket(entry.getValue(),formatMessage("所有人",orignalMessage));
}
}
}
privatevoidshowOnlineUsers()throwsIOException{
StringBuilderusers=newStringBuilder();
users.append("当前在线的用户有:\n");
for(StringnickName:ChatServer.nickNameSocketMap.keySet()){
users.append("【").append(nickName).append("】\n");
}
write(users.toString());
}
privatevoidwrite(Stringmessage)throwsIOException{
SocketUtils.writeToDataOutputStream(dos,message);
}
}
客户端线程
importjava.io.DataInputStream;
importjava.io.IOException;
publicclassClientMessageReceiverimplementsRunnable{
privateDataInputStreamdis;
privatebooleantimeToStop=false;
publicClientMessageReceiver(DataInputStreamdis){
this.dis=dis;
}
@Override
publicvoidrun(){
while(!timeToStop){
try{
System.out.println(dis.readUTF());
}catch(IOExceptione){
if("Connectionreset".equals(e.getMessage())){
System.out.println("与服务器的连接已中断!");
break;
}
if(!timeToStop){
e.printStackTrace();
}
}
}
}
publicvoidstop(){
timeToStop=true;
}
}
服务器端程序
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.HashMap;
importjava.util.Map;
publicclassChatServer{
publicstaticfinalStringEXIT="exit";
publicstaticfinalintPORT=8888;
staticMapnickNameSocketMap=newHashMap<>();
publicstaticvoidmain(String[]args){
try(ServerSocketss=newServerSocket(PORT)){
System.out.println("聊天室服务器端已启动,正在监听"+PORT+"端口");
while(true){
try{
Socketsocket=ss.accept();
System.out.println("有新用户连接到服务器端,信息为:"+socket);
newThread(newChatServerRunnable(socket)).start();
}catch(Exceptione){
e.printStackTrace();
}
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
客户端程序
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importjava.util.Scanner;
publicclassChatClient{
privatestaticScannerscanner=newScanner(System.in);
publicstaticvoidmain(String[]args){
try(Socketsocket=newSocket("127.0.0.1",8888);
DataInputStreamdis=newDataInputStream(socket.getInputStream());
DataOutputStreamdos=newDataOutputStream(socket.getOutputStream())){
ClientMessageReceivermessageReceiver=newClientMessageReceiver(dis);
newThread(messageReceiver).start();
Stringinput=null;
do{
input=scanner.nextLine();
write(dos,input);
}while(!ChatServer.EXIT.equals(input));
messageReceiver.stop();
}catch(IOExceptione){
e.printStackTrace();
}
}
privatestaticvoidwrite(DataOutputStreamdos,Stringmessage)throwsIOException{
dos.writeUTF(message);
dos.flush();
}
}
运行说明
启动服务器:
启动第一个客户端,输入客户昵称:
服务器监听到了这个事件:
获取所有用户列表,发送给所有用户“hhh”的信息:
服务器接收到这个事件:
用户1向用户2发送私聊消息:
用户2收到用户1的消息:
客户端用户退出的时候,该线程终止。
没客户端用户,服务器也正常跑自己的事。
到此这篇关于基于Java的Socket多客户端Client-Server聊天程序的实现的文章就介绍到这了,更多相关JavaSocket多客户端Client-Server聊天内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。