作业要求:
必做:多个客户端之间能够相互聊天
选做: 1、能够在多个客户端之间进行文件的传送
2、能够在多个客户端之间实现发送表情包功能
步骤:
本作业采用Java程序语言完成,使用了Socket套接字跟Swing组件
首先在服务器端,需要实现一个GUI界面,一旦运行服务器,能够告诉使用者,服务器已经开启!界面效果如图

接着使用使用套接字创建了服务器,服务器端使用while循环一直监听客户端的连接,当服务器接收到客户端的连接请求时,服务器为每个客户端创建一个对应的Socket,并添加到ArrayList中保存,然后开启线程。
static ArrayList<Socket> socketList = new ArrayList<>();
socket = serverSocket.accept();
socketList.add(socket);
new Thread(new SendThread(socket,socketList)).start();
服务器端的多线程功能首先是判断客户端的用户名是否重复,不重复则保存客户端及用户名,主要接收客户端的消息并且转发给所有客户端
private void CheckMessage(String message){
if (message.trim().contains(USER_CONTENT_SPILIT)){
//System.out.println("2");
String[] arrayContent = message.split(USER_CONTENT_SPILIT);
//System.out.println("客户端用户名:"+arrayContent[0]);
if (arrayContent!=null && arrayContent.length==1){
String name = arrayContent[0];
if (users.containsValue(name)){
String userExit = "系统消息:"+name+"用户名重复,请重新输入";
SendClient(socket, userExit);
Server.socketList.remove(socket);
}else{
//System.out.println("4");
users.put(socket, name);
String ok = "用户名可以使用";
SendClient(socket,ok);
String welcomemessage = "系统消息:欢迎"+name+"来到聊天室!";
SendAllClient(socketList,welcomemessage);
}
}
}else{
SendAllClient(socketList,message);
}
}
CheckMessage(String message)方法是用来检查消息是否是用户名的,使用用户名分隔符“#@#”来判断,这是特殊规定的;不是用户名,则SendAllClient(socketList,welcomemessage)方法来把接收的所有的消息发送给客户端
private void SendAllClient(ArrayList<Socket> socketList,String message){
if(socketList.size()!=0){
for (Socket clientSocket: socketList){
SendClient(clientSocket,message);
Collection<String> values = users.values();
Iterator<String> it = values.iterator();
String names = "";
while(it.hasNext()){
Object value = it.next();
names = names + value + USER_CONTENT_SPILIT;
}
if(names!=null)
Sendname(clientSocket,names);
}
}
}
服务器的主要功能是这样
在客户端首先运行会出现一个登陆界面,如图

登陆的时候,首先会进行判空,如果用户名或者密码为空则会进行提示,如果不为空会发送用户名到服务器进行判断是否重复,不重复则跳到聊天界面,如图

使用两个多线程,一个用来接收服务端发送的消息,把从服务器端接收到的消息添加到图形化界面上;另一个用来客户端自己发送消息,把从图形化界面接收到的输入消息发送到服务器。
private void sendmessage(){
new Thread(){
public void run(){
bWritermessage = Client.getWriter(socketmessage);
String message = input.getText();
if(message==null || message.trim().equals("")){
textmessage.append("聊天消息不能为空!"+"\n");
}else{
try {
bWritermessage.write(message);
bWritermessage.newLine();
bWritermessage.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
input.setText("");
}
}.start();
}
private void receive(){
new Thread(){
public void run(){
try{
String data ;
bReader = Client.getReader(socketmessage);
while((data= bReader.readLine())!= null){
textusers.setText("");
if(data.contains("#@#")){
String[] name = data.split("#@#");
for (int i = 0;i < name.length; i++){
textusers.append(name[i] + "\n");
}
}else{
textmessage.append(data+"\n");
}
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
结论跟心得:
本次作业只实现了基本要求,没有实现传送文件跟发表情包功能,能够在多个客户端之间相互通信!并且登陆的时候能够检查用户名跟密码是否为空,用户名是否重复,同时也监听了键盘的回车键,即按下回车键能够发送消息!
很遗憾,传送文件的功能没有实现,客户端图形界面上的选择文件按钮点击能够选择文件并获取选择文件的路径,但是并不能发送,本来是能够单独传送文件的,原因主要是Java多线程基于GUI是不安全的,而我也没有找到合适的解决办法,只能够实现基础功能!等以后找到解决办法再来实现选做功能!
网友评论