一:软件实现功能简介。
1.整个软件采用C/S结构,分为客户端与服务端。客户端为用户提供了一下功能:
(1)可以在线进行注册,登陆,若已注册用户密码忘记则可以通过找回密码功能在线成功的取回自己的密码。
(2)已登录用户不能进行异地登陆。
(3)用户可以与在线的任意其他用户进行通信或是用户向其他在线所有用户通信,用户可以知道在线人数以及谁下线和服务器是否关闭等消息。
(4)在线用户之间可以相互传输任何格式的文件,并向接受文件用户提供传输文件的大小,名称以及文本格式。
(5)本软件为用户提供了mp3播放器,用户可以在聊天的同时听mp3(需要mp3解码jar包)。
(6)服务器端共管理人员使用,它记录着每个用户的聊天信息并显示出来供管理员监督,同时管理员还可以向任何用户或所有用户发送系统信息。
(7)服务端提供了动态设置IP地址及端口功能,客户端也提供同样的功能。
二:软件使用简介。
已注册用户可以直接通过客户端登陆,如果合法性验证通过则会进入聊天界面。如图:
然后你可以进行连接一边生成在线状态。在连接之前你必须设置服务端所在IP地址,如果成功连接的化会显示如下界面:
否则会出现对话框提示:
三:软件开发平台:
NetBeans,JDK1.6以及MySQL数据库
三:软件工作原理。
本软件编写全部用Java语言完成,主要是利用Java基本socket编程,通过套接字进行数据的传输。由于本人精力有限服务端只是采用了多线程技术以和每个客户端建立套接字
连接,并维持它们之间的通信。客户端采用单线程负责与服务器的通信。对应的客户端和服务端的两个线程都利用了while循环对输入流进行监听然后根据条件对不同的信息进行
不同的回应,服务端则维持一个链式存储结构将每个连接的客户端的socket信息保存以便把用户对其它用户的请求转发给特定的用户,服务端则作为一个桥梁(也可以理解为中转站)
完成不同用户之间的通信。
另外本软件采用了MySQL数据库负责合法用户信息的存储,另外还有一个功能就是保存用户是否在线的变量标志T=0。当一个用户登陆成功后则T被相应代码修改为1,如果用户
有一同样的新名再次登陆在条件语句会判断T是否等于0如果不是则说明用户已登录便提示用户“该用户已登录!”,这样确保在线用户的唯一性。在用户推出聊天的时候则会将T至于0.
另外本人编写了一个小型的mp3播放器,实现了一些简单功能比如用户可以将电脑上的mp3文件添加到List中,然后用户可以对歌曲名进行点击播放并可以在不同歌曲之间跳转。
关键代码:
1. 服务器端主要类三个:Main类,ServerL类和ServerR类
Main类负责服务端界面的生成。
ServerL类有Main创建并启动监听来自于用户端的请求连接。
ServerR类有ServerL创建并启动负责和对应的客户端通信。
关键代码如下:

Main.java: 

 public void actionPerformed(ActionEvent e) { 

 Object obj = e.getSource(); 

 if (obj == startServer || obj == startItem) { //启动服务端 

 startService(); 

 } 

 else if (obj == stopServer || obj == stopItem) { //停止服务端 

 int j=JOptionPane.showConfirmDialog( 

 this,"真的停止服务吗?","停止服务", 

 JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE); 


 if (j==JOptionPane.YES_OPTION){ 

 stopService(); 

 } 

 } 

 else if (obj == portSet || obj == portItem) { //端口设置 

 PortConf portConf = new PortConf(this); 

 portConf.show(); 

 } 

 else if (obj == exitButton || obj == exitItem) { //退出程序 

 int j=JOptionPane.showConfirmDialog( 

 this,"真的要退出吗?","退出", 

 JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE); 


 if(j == JOptionPane.YES_OPTION){ 

 stopService(); 


 System.exit(0); 

 } 

 } 

 else if (obj == helpItem) { //菜单栏中的帮助 

 //调出帮助对话框 

 Help helpDialog = new Help(this); 

 helpDialog.show(); 

 } 

 else if (obj == sysMessage || obj == sysMessageButton) { //发送系统消息 

 sendSystemMessage(); 

 } 

 } 

 public void startService(){ 

 try{ 

 serverSocket = new ServerSocket(port,10); 

 messageShow.append("服务端已经启动,在"+port+"端口侦听...\n"); 


 startServer.setEnabled(false); 

 startItem.setEnabled(false); 

 portSet.setEnabled(false); 

 portItem.setEnabled(false); 


 stopServer .setEnabled(true); 

 stopItem .setEnabled(true); 

 sysMessage.setEnabled(true); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 

 userLinkList = new UserLinkList(); 

 listenThread = new ServerL(serverSocket,combobox, 

 messageShow,showStatus,userLinkList); 

 listenThread.start(); 

 } 


 /** 

 * 关闭服务端 

 */ 

 public void stopService(){ 

 try{ 

 //向所有人发送服务器关闭的消息 

 sendStopToAll(); 

 listenThread.isStop = true; 

 serverSocket.close(); 


 int count = userLinkList.getCount(); 


 int i =0; 

 while( i < count){ 

 Node node = userLinkList.findUser(i); 


 node.input .close(); 

 node.output.close(); 

 node.socket.close(); 


 i ++; 

 } 


 stopServer .setEnabled(false); 

 stopItem .setEnabled(false); 

 startServer.setEnabled(true); 

 startItem.setEnabled(true); 

 portSet.setEnabled(true); 

 portItem.setEnabled(true); 

 sysMessage.setEnabled(false); 


 messageShow.append("服务端已经关闭\n"); 


 combobox.removeAllItems(); 

 combobox.addItem("所有人"); 

 } 

 catch(Exception e){ 

 //System.out.println(e); 

 } 

 } 


 /** 

 * 向所有人发送服务器关闭的消息 

 */ 

 public void sendStopToAll(){ 

 int count = userLinkList.getCount(); 


 int i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 try{node.output.writeUTF("服务器"); 

 node.output.flush(); 

 node.output.writeUTF("服务关闭"); 

 node.output.flush(); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 


 i++; 

 } 

 }服务端向指定用户发送系统信息 

 public void sendMsgToAll(String msg){ 

 int count = userLinkList.getCount();//用户总数 


 int i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 try{ 

 node.output.writeUTF("系统信息"); 

 node.output.flush(); 

 node.output.writeUTF(msg); 

 node.output.flush(); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 


 i++; 

 } 


 sysMessage.setText(""); 

 } 


 public void sendSystemMessage(){ 

 String toSomebody = combobox.getSelectedItem().toString(); 

 String message = sysMessage.getText() + "\n"; 


 messageShow.append(message); 



 if(toSomebody.equalsIgnoreCase("所有人")){ 

 sendMsgToAll(message); 

 } 

 else{ 


 Node node=userLinkList.findUser(toSomebody); 


 try{ 

 node.output.writeUTF("系统信息"); 

 node.output.flush(); 


 node.output.writeUTF(message); 


 node.output.flush(); 

 //node.output.writeObject("dfdsfdsfsdsf"); 

 //node.output.flush(); 

 } 

 catch(Exception e){ 

 System.out.println(e); 

 //return; 

 } 

 sysMessage.setText(""); 

 } 

 } 



 /*public static void main(String[] args) { 

 Main app = new Main(); 

 }*/ 

} 


ServerL类: 


 * To change this template, choose Tools | Templates 

 * and open the template in the editor. 

 */ 


package server; 


import java.awt.*; 

import java.awt.event.*; 

import javax.swing.*; 

import javax.swing.event.*; 

import java.io.*; 

import java.net.*; 

 public class ServerL extends Thread { 

 ServerSocket server; 


 JComboBox combobox; 

 JTextArea textarea; 

 JTextField textfield; 

 UserLinkList userLinkList;//用户链表 

 Node client; 

 ServerR recvThread; 


 public boolean isStop; 


 /* 

 * 聊天服务端的用户上线于下线侦听类 

 */ 

 public ServerL(ServerSocket server,JComboBox combobox, 

 JTextArea textarea,JTextField textfield,UserLinkList userLinkList){ 


 this.server = server; 

 this.combobox = combobox; 

 this.textarea = textarea; 

 this.textfield = textfield; 

 this.userLinkList = userLinkList; 


 isStop = false; 

 } 

 public void sendUserList(){ 

 String userlist = ""; 

 int count = userLinkList.getCount(); 


 int i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 userlist += node.username; 

 userlist += '\n'; 

 i++; 

 } 


 i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 try{ 

 node.output.writeUTF("用户列表"); 

 node.output.flush(); 

 node.output.writeUTF(userlist); 

 node.output.flush(); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 

 i++; 

 } 

 } 


 public void run(){ 

 while(!isStop && !server.isClosed()){ 

 try{ 

 client = new Node(); 

 client.socket = server.accept(); 

 client.output = new DataOutputStream(client.socket.getOutputStream()); 

 //client.output.flush(); 

 client.input = new DataInputStream(client.socket.getInputStream()); 

 //client.input.readByte(); 

 client.username =client.input.readUTF(); 



 combobox.addItem(client.username); 

 //if(userLinkList.findUser(client.username)==null) 

 userLinkList.addUser(client); 

 textarea.append("用户 " + client.username + " 上线" + "\n"); 

 textfield.setText("在线用户" + userLinkList.getCount() + "人\n"); 


 recvThread = new ServerR(textarea,textfield, 

 combobox,client,userLinkList); 

 recvThread.start(); 

 } 

 catch(Exception e){ 



 } 

 } 

 } 

 } 

ServerR类: 

package server; 


import javax.swing.*; 

import java.awt.*; 

import java.awt.event.*; 

import javax.swing.border.*; 

import java.io.*; 

import java.net.*; 

public class ServerR extends Thread { 

 JTextArea textarea; 

 JTextField textfield; 

 JComboBox combobox; 

 Node client; 

 // Node node=new Node(); 

 UserLinkList userLinkList;//用户链表 


 public boolean isStop; 


 public ServerR(JTextArea textarea,JTextField textfield, 

 JComboBox combobox,Node client,UserLinkList userLinkList){ 


 this.textarea = textarea; 

 this.textfield = textfield; 

 this.client=client; 

 this.userLinkList = userLinkList; 

 this.combobox = combobox; 


 isStop = false; 

 } 

循环根据用户端发送的不同条件作出不同的回应 

 @Override 

 public void run(){ 


 sendUserList();发送用户列表确保每一个用户上线后能及时更新每个其他在线用户的列表 

 while(true){//!isStop&&!client.socket.isClosed()){ 

 try{ 

 String type = client.input.readUTF();判断用户端发送的请求类型 


 if(type.equalsIgnoreCase("聊天")){ 

 String toSomebody = client.input.readUTF(); 



 String message = client.input.readUTF(); 

 //String mess = toSomebody + "发来信息"; 

 String msg =client.username+"对 " 

 + toSomebody 

 + " 说 : " 

 + message 

 + "\n"; 



 textarea.append(msg); 

 if(toSomebody.equalsIgnoreCase("所有人")){ 

 sendToAll(msg); 

 } 

 else{ 

 Node node = userLinkList.findUser(toSomebody); 

 if(node != null){ 

 node.output.writeUTF("聊天"); 

 node.output.flush(); 

 node.output.writeUTF(msg); 

 node.output.flush(); 

 } 

 } 

 } 


 if(type.equalsIgnoreCase("用户下线")){ 

 Node node = userLinkList.findUser(client.username); 

 userLinkList.delUser(node); 


 String msg = "用户 " + client.username + " 下线\n"; 

 int count = userLinkList.getCount(); 

 combobox.removeItem(client.username); 

 //combobox.removeAllItems(); 

 //combobox.addItem("所有人"); 

 //int i = 0; 

 //while(i < count){ 

 //node = userLinkList.findUser(i); 

 //if(node == null) { 

 //i ++; 

 //continue; 

 //} 


 //combobox.addItem(node.username); 

 //i++; 

 //} 

 //combobox.setSelectedIndex(0); 


 //textarea.append(msg); 

 textfield.setText("在线用户" + userLinkList.getCount() + "人\n"); 


 sendToAll(msg);//向所有人发送消息 

 sendUserList();//重新发送用户列表,刷新 


 break; 

 } 


 if(type.equalsIgnoreCase("文件传输")){ 

 /* String someone; 

 String receiveFile="G:\\"; 

 someone=client.input.readUTF(); 

 // Node node = userLinkList.findUser(someone); 

 // DataOutputStream Soutstream= node.output; 

 // node.input.readByte(); 

 String Fname=client.input.readUTF(); 

 Long len = client.input.readLong(); 

 receiveFile+=Fname; 

 DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(receiveFile))); 

 while (true) { 

 int read = 0; 

 int bufferSize = 3000; 

 byte[] buf = new byte[bufferSize]; 


 if (client.input!= null) { 

 read = client.input.read(buf); 

 } 



 else if(read == -1) { 

 break; 

 } 

 fileOut.write(buf, 0, read); 

 } 

 fileOut.close(); 


 // DataInputStream inputStream=new DataInputStream(client.socket.getInputStream()); 

 // client.output.writeByte(0x1); 

 // client.output.flush();*/ 



 String someone=client.input.readUTF(); 

 Node node = userLinkList.findUser(someone); 

 //DataOutputStream Soutstream= node.output; 

 //node.input.readByte(); 

 String Fname=client.input.readUTF(); 

 Long len = client.input.readLong(); 

 String msg=client.username+"申请给你发送名为"+Fname+"大小为"+(len/1024)+"KB"+"的文件"+"\n"; 


 node.output.writeUTF("接受文件"); 

 node.output.flush(); 

 node.output.writeUTF(msg); 

 node.output.flush(); 


 node.output.writeUTF(Fname); 

 node.output.flush(); 


 int bufferSize = 3000; 

 byte[] buf = new byte[bufferSize]; 


 while (true) { 

 int read = 0; 

 if (client.input != null) { 

 read = client.input.read(buf); 




 node.output.write(buf, 0, read); 

 node.output.flush(); 

 } 

 if (read==0) 

 { break;} 


 } 

 System.out.println("文件传输完成"); 

 } 

 }catch(Exception e ){ 

 System.out.println(e); 

 } 

 } 

 } 


 public void sendToAll(String msg){ 

 int count = userLinkList.getCount(); 

 //textarea.append(msg); 

 int i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 try{ 

 node.output.writeUTF("系统信息"); 

 node.output.flush(); 

 node.output.writeUTF(msg); 

 node.output.flush(); 

 textarea.append(msg); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 


 i++; 

 } 

 } 


 /* 

 * 向所有人发送用户的列表 

 */ 

 public void sendUserList(){ 

 String userlist = ""; 

 int count = userLinkList.getCount(); 


 int i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 userlist += node.username; 

 userlist += '\n'; 

 i++; 

 } 


 i = 0; 

 while(i < count){ 

 Node node = userLinkList.findUser(i); 

 if(node == null) { 

 i ++; 

 continue; 

 } 


 try{ 

 node.output.writeUTF("用户列表"); 

 node.output.flush(); 

 node.output.writeUTF(userlist); 

 node.output.flush(); 

 } 

 catch (Exception e){ 

 System.out.println(e); 

 } 

 i++; 

 } 

 } 

}