有6个模块
1.用户登录
2.两两私聊
3.群发消息
4.退出登录
5.关闭服务器
6.文件传输
一、用户登录
客户端:
1、发送登录信息:LOGIN|Username
处理USERLISTS命令:所有在线用户的用户名
2、处理新上线用户信息:ADD|username
服务器端:
1、得到所有在线用户信息名称,发回给客户端:USERLISTS|user1_user2_user3
2、将当前登录的Socket信息放入Arraylist中
3、将当前登录用户的信息(用户名),发送给已经在线的其他用户:ADD|userName
二、两两私聊
客户端:
1、选择用户
2、组织一个交互协议,发送到服务器:MSG|SenderName|RecName|MSGInfo
3、接收服务器转发回的消息
服务器端:
1、通过RecName用户名查找,找到目标SocketChat
2、向目标对象发送消息:MSG|SenderName|MSGInfo
三、群聊
MSG|Sendername|ALL|MSGInfo
四、用户退出连接
客户端:
1、向服务器发送下线消息:OFFLINE|username
2、关闭ClientChat,清空在线用户列表
3、处理下线用户信息:DEL|username
删除用户列表中的username
服务器端:
1、处理OFFLINE
2、向所有的其他在线用户发送用户下线消息:DEL|username
3、清除ArrayList中的当前用户信息(socketChat)
五、服务器关闭
客户端:
1、处理CLOSE命令:界面显示服务器关闭
2、关闭ClientChat
3、清空在线用户列表
服务器端:
1、向所有在线用户发送关闭服务器的信息:CLOSE
2、遍历Arraylist将其中的每一个SocketChat关闭
3、ArrayList要清空
4、关闭SokcetListener
5、关闭ServerSocket
六、文件传输
客户端:
准备工作:1,2,3
//1从本地选中一个文件,获取其文件相关信息(文件名,文件长度)
//2创建文件传输的服务器,与服务器接通
//3组织文件传输交互协议进行传输
//FILETRANS|sendername|recname|文件名|文件长度|IP|Port
处理服务器转发的内容,处理该内容确认是接收还是拒收,如果接收,建立连接通道接收文件(即开启fileRec线程)
如果拒收,组织拒收交互协议(FILECANCEL|拒收者|被拒收者)发送给服务器
服务器端:
接收发来的消息串,提取发送者+接收者+发送内容+传送文件的IP和Port 进行转发
服务器收到交互协议:FILECANCEL|拒收者|被拒收者 重新组织交互协议FILECANCELReturn|拒收者 要通知被拒收者,被拒收的消息
群发的流程图比较简单就没有画
六、文件传输
以下代码只需修改以下IP地址和端口号即可运行,后期准备对发送消息的内容进行加密用Base64加密方法加密
客户端代码:
packagerjxy.lkl.Client;import java.io.*;import java.net.*;public class ClientChat extendsThread {
Socket socket;
BufferedReader br= null;
PrintWriter pw= null;
String UserName;publicClientChat(Socket socket, String userName) {this.socket =socket;
UserName=userName;try{
br= new BufferedReader(newInputStreamReader(socket.getInputStream(),"UTF-8"));
pw= new PrintWriter(new BufferedWriter(newOutputStreamWriter(
socket.getOutputStream(),"UTF-8")));
}catch(Exception e) {
e.printStackTrace();
}//约定一个登录的交互协议Login|username
sendMSG("Login|"+UserName);
}public voidsendMSG(String str){
pw.println(str);
pw.flush();
}//断开socket连接
public voidcloseChat(){try{if(socket!=null) socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}//处理服务器发过来的在线用户List ,交互协议为:USERLISTS|user1_user2_user3
public voidrun() {try{
String str= "";while((str = br.readLine())!=null){
System.out.println("---"+str+"---");
String comms[]= str.split("[|]");if(comms[0].equals("USERLISTS")){
String users[]= comms[1].split("_");
ClientMG.getClientMG().addItems(users);
}else if(comms[0].equals("ADD")){
ClientMG.getClientMG().addItem(comms[1]);
}else if(comms[0].equals("MsgReturn")){//"MsgReturn|"+sender+"|"+msg
String sender = comms[1];
String msg= comms[2];
ClientMG.getClientMG().setLog("【"+sender+"】:");
ClientMG.getClientMG().setLog(msg);
}else if(comms[0].equals("DEL")){//交互协议为:"DEL|"+UserName
String sUser = comms[1];
ClientMG.getClientMG().removeItem(sUser);
ClientMG.getClientMG().setLog(sUser+"已下线");
}else if(comms[0].equals("CLOSE")){
ClientMG.getClientMG().setLog("服务器已关闭");//关闭ClientChat
ClientMG.getClientMG().getClientChat().closeChat();//清空在线用户列表
ClientMG.getClientMG().clearItems();
}else if(comms[0].equals("FILETRANS")){//"FILETRANS|"+sender+"|"+sFname+"|"+finfo.length()+"|"+IP+"|"+Port
String sender = comms[1];
String fileName= comms[2];int filelen = Integer.parseInt(comms[3]);
String sIP= comms[4];int port = Integer.parseInt(comms[5]);//调用ClientMG中的接收文件的方法
ClientMG.getClientMG().recFile(sender, fileName, filelen, sIP, port);
}else if(comms[0].equals("FILECANCEL")){
ClientMG.getClientMG().cancelFileTrans();
}else if (comms[0].equals("FILECANCELReturn")){//FILECANCELReturn|拒收者A
ClientMG.getClientMG().setLog(comms[1]+"取消了传输。。。");
}
}
}catch(Exception e) {
e.printStackTrace();
}finally{try{if (br != null)
br.close();if (pw != null)
pw.close();if (socket != null)
socket.close();
}catch(Exception e2) {
e2.printStackTrace();
}
}
}
}
packagerjxy.lkl.Client;importjava.awt.BorderLayout;public class ClientForm extendsJFrame {privateJPanel contentPane;publicJPanel panel;publicJLabel lblIp;publicJTextField txtIP;publicJLabel label_1;publicJTextField txtPort;publicJButton btnLogin;publicJButton btnExit;publicJPanel panel_1;publicJButton btnSend;
Socket socket;
BufferedReader br=null;
PrintWriter pw=null;publicJScrollPane scrollPane;publicJTextArea txtLog;publicJScrollPane scrollPane_1;publicJTextArea txtSend;publicJLabel label;publicJTextField txtUser;publicJScrollPane scrollPane_2;publicJList lOnlines;
DefaultListModel items=new DefaultListModel();publicJButton sendToAll;publicJButton FileTranbutton;publicJProgressBar FileprogressBar;/*** Launch the application.*/
public static voidmain(String[] args) {
EventQueue.invokeLater(newRunnable() {public voidrun() {try{
ClientForm frame= newClientForm();
frame.setVisible(true);
ClientMG.getClientMG().setClientForm(frame);
}catch(Exception e) {
e.printStackTrace();
}
}
});
}/*** Create the frame.*/
publicClientForm() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 513, 583);
contentPane= newJPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
panel= newJPanel();
panel.setLayout(null);
panel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "\u767B\u5F55\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBounds(11, 10, 476, 64);
contentPane.add(panel);
lblIp= new JLabel("IP:");
lblIp.setHorizontalAlignment(SwingConstants.RIGHT);
lblIp.setBounds(10, 19, 35, 31);
panel.add(lblIp);
txtIP= newJTextField();
txtIP.setText("10.12.50.10");
txtIP.setColumns(10);
txtIP.setBounds(55, 22, 97, 24);
panel.add(txtIP);
label_1= new JLabel("\u7AEF\u53E3:");
label_1.setHorizontalAlignment(SwingConstants.RIGHT);
label_1.setBounds(154, 19, 35, 31);
panel.add(label_1);
txtPort= newJTextField();
txtPort.setText("8899");
txtPort.setColumns(10);
txtPort.setBounds(190, 21, 35, 26);
panel.add(txtPort);
btnLogin= new JButton("\u767B\u5F55");
btnLogin.addActionListener(newBtnLoginActionListener());
btnLogin.setBounds(337, 22, 65, 25);
panel.add(btnLogin);
btnExit= new JButton("\u9000\u51FA");
btnExit.addActionListener(newBtnExitActionListener());
btnExit.setBounds(401, 22, 65, 25);
panel.add(btnExit);
label= new JLabel("\u7528\u6237\u540D:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
label.setBounds(228, 19, 50, 31);
panel.add(label);
txtUser= newJTextField();
txtUser.setText("visiter");
txtUser.setColumns(10);
txtUser.setBounds(281, 22, 50, 26);
panel.add(txtUser);
panel_1= newJPanel();
panel_1.setLayout(null);
panel_1.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "\u64CD\u4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel_1.setBounds(10, 414, 477, 121);
contentPane.add(panel_1);
btnSend= new JButton("\u53D1\u9001\u6D88\u606F");
btnSend.addActionListener(newBtnSendActionListener());
btnSend.setBounds(357, 82, 110, 23);
panel_1.add(btnSend);
scrollPane_1= newJScrollPane();
scrollPane_1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane_1.setBounds(10, 24, 457, 48);
panel_1.add(scrollPane_1);
txtSend= newJTextArea();
scrollPane_1.setViewportView(txtSend);
sendToAll= new JButton("\u7FA4\u53D1\u6D88\u606F");
sendToAll.addActionListener(newButtonActionListener());
sendToAll.setBounds(254, 82, 93, 23);
panel_1.add(sendToAll);
FileTranbutton= new JButton("\u4F20\u8F93\u6587\u4EF6");
FileTranbutton.addActionListener(newButtonActionListener_1());
FileTranbutton.setBounds(10, 82, 81, 23);
panel_1.add(FileTranbutton);
FileprogressBar= newJProgressBar();
FileprogressBar.setBounds(98, 92, 146, 8);
panel_1.add(FileprogressBar);
scrollPane= newJScrollPane();
scrollPane.setBorder(new TitledBorder(null, "\u804A\u5929\u8BB0\u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane.setBounds(11, 84, 309, 332);
contentPane.add(scrollPane);
txtLog= newJTextArea();
scrollPane.setViewportView(txtLog);
scrollPane_2= newJScrollPane();
scrollPane_2.setBorder(new TitledBorder(null, "\u5728\u7EBF\u7528\u6237", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane_2.setBounds(323, 83, 164, 332);
contentPane.add(scrollPane_2);
lOnlines= newJList(items);
scrollPane_2.setViewportView(lOnlines);
}//登录
private class BtnLoginActionListener implementsActionListener {public voidactionPerformed(ActionEvent arg0) {
String ip=txtIP.getText().trim();int port =Integer.parseInt(txtPort.getText().trim());
String socketname=txtUser.getText().trim();
ClientMG.getClientMG().connect(ip, port, socketname);
}
}//发送信息
private class BtnSendActionListener implementsActionListener {public voidactionPerformed(ActionEvent arg0) {//选中要聊天的用户
String sendUsername = null;if(lOnlines.getSelectedIndex()>=0){//得到用户选择的名称
String targetUsername =lOnlines.getSelectedValue().toString();
System.out.println(targetUsername);//发送者的名称
sendUsername =txtUser.getText().trim();//消息体
String sMSG =txtSend.getText();//交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG//包装后的消息发送出去
String strSend = "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG;
System.out.println(strSend);
ClientMG.getClientMG().getClientChat().sendMSG(strSend);
ClientMG.getClientMG().setLog("I send To "+targetUsername+":");
ClientMG.getClientMG().setLog(sMSG);//清空发送消息框
txtSend.setText("");
}
}
}//推出操作
private class BtnExitActionListener implementsActionListener {public voidactionPerformed(ActionEvent arg0) {//组织推出交互协议"OFFLINE|"+username
String sendMSG = "OFFLINE|"+txtUser.getText().trim();
ClientMG.getClientMG().getClientChat().sendMSG(sendMSG);//断开与服务器的socket连接
ClientMG.getClientMG().getClientChat().closeChat();
ClientMG.getClientMG().clearItems();//清空列表
}
}private class ButtonActionListener implementsActionListener {public voidactionPerformed(ActionEvent e) {//发送者的名称
String sendUsername =txtUser.getText().trim();//消息体
String sMSG =txtSend.getText();//交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG//包装后的消息发送出去
String strSend = "MSG|"+sendUsername+"|ALL|"+sMSG;
System.out.println(strSend);//协议为:"MSG|"+sendUsername+"|ALL|"+msg
ClientMG.getClientMG().getClientChat().sendMSG(strSend);
txtSend.setText("");
}
}//传输文件
private class ButtonActionListener_1 implementsActionListener {public voidactionPerformed(ActionEvent e) {//1从本地选中一个文件,获取其文件相关信息(文件名,文件长度)//2创建文件传输的服务器,与服务器接通//3组织文件传输交互协议进行传输//FILETRANS|sendername|recname|文件名|文件长度|IP|Port
File finfo= null;//用于文件选择的对象jFileChooser
JFileChooser jFileChooser = newJFileChooser();int result = jFileChooser.showOpenDialog(null);if(result==JFileChooser.APPROVE_OPTION){
finfo= newFile(jFileChooser.getSelectedFile().getAbsolutePath());
String sFname=finfo.getName();//在用户列表中选择目标用户
if(lOnlines.getSelectedIndex()!=-1){
String sTarget= lOnlines.getSelectedValue().toString();//得到目标用户
String sender =txtUser.getText().trim();//得到新开服务器的IP+Port
String IPandPort =ClientMG.getClientMG().CreateFileTranServer(finfo);//组织交互协议串,然后发送 FILETRANS+发送者+目标用户+文件名+文件的长度+IP和端口号
String strSend = "FILETRANS|"+sender+"|"+sTarget+"|"+sFname+"|"+finfo.length()+"|"+IPandPort;
ClientMG.getClientMG().getClientChat().sendMSG(strSend);
}
}
}
}
}
packagerjxy.lkl.Client;importjava.io.File;importjava.io.IOException;importjava.net.InetAddress;importjava.net.ServerSocket;importjava.net.Socket;importjava.net.UnknownHostException;importjavax.swing.JOptionPane;public classClientMG {//实现管理类的单例化
private static final ClientMG clientMG = newClientMG();publicClientMG() {
}public staticClientMG getClientMG(){returnclientMG;
}//操作图形化界面
ClientForm cWin;
ClientChat cChat;public voidsetClientForm(ClientForm cf){
cWin=cf;
}//设置界面中的消息记录
public voidsetLog(String str){
cWin.txtLog.append(str+"\r\n");
}publicClientChat getClientChat(){returncChat;
}//新上线的用户添加到JList中
public voidaddItem(String username){
cWin.items.addElement(username);
}public voidaddItems(String [] sItems){for(String username : sItems) {
addItem(username);
}
}//一旦断开连接,清空JList中的用户//清空单个
public voidremoveItem(String str){
cWin.items.removeElement(str);
}//清空所有
public voidclearItems(){
cWin.items.clear();
}public void connect(String IP,intport,String Username){try{
Socket socket= newSocket(IP,port);
ClientMG.getClientMG().setLog("已连接到服务器 ");
cChat= newClientChat(socket,Username);
cChat.start();
}catch(Exception e) {
e.printStackTrace();
}
}
FileListener filelistener;//创建文件传输的服务器
publicString CreateFileTranServer(File file){try{
ServerSocket server= new ServerSocket(8881);
String IP=InetAddress.getLocalHost().getHostAddress();
filelistener= newFileListener(server,file);
filelistener.start();return IP+"|"+8881;
}catch(Exception e) {
e.printStackTrace();
}return "";
}//接收文件
public void recFile(String sender,String fName,int len,String IP,intport){//文件名|文件长度|IP|Port//4判断是否要接收? JOptionPane->confirm//5同意接收,连接服务器进行文件传输//6拒绝接收,向服务器发回拒接接收的消息:FILECANCEL|sendername|recname
JOptionPane msg= newJOptionPane();int result = msg.showConfirmDialog(null, sender+"发送文件【"+fName+"】,\r\n是否接收?", "文件传输确认", JOptionPane.YES_NO_OPTION);if(result ==JOptionPane.YES_NO_OPTION){//确认接收
try{
Socket socket= newSocket(IP,port);newfileRec(socket, fName, len).start();
}catch(Exception e) {
e.printStackTrace();
}
}else{//如果拒收 FILECANCEL|FromUser|toUser,sender给我发消息,某某某拒绝了,就通知sender,某某某拒绝了你的文件传输
String strSend = "FILECANCEL|"+this.getClientChat().UserName+"|"+sender;this.getClientChat().sendMSG(strSend);this.setLog("您已拒接了"+sender+"的文件传输");
}
}//对方取消文件传递
public voidcancelFileTrans(){
filelistener.cancelFileTrans();//this.setLog("对方取消了文件传输!!!");
}
}
packagerjxy.lkl.Client;import java.io.*;import java.net.*;public class FileListener extendsThread {
ServerSocket fserver;
File filetrans;publicFileListener(ServerSocket fserver, File filetrans) {this.fserver =fserver;this.filetrans =filetrans;
}//取消传输
public voidcancelFileTrans(){if(fserver!=null){try{
fserver.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}public voidrun() {
Socket sfile= null;
DataInputStream dis= null;
DataOutputStream dos= null;try{
sfile=fserver.accept();
dis= new DataInputStream(newFileInputStream(filetrans));
dos= newDataOutputStream(sfile.getOutputStream());//有关进度条属性的设置
ClientMG.getClientMG().cWin.FileprogressBar.setValue(0);
ClientMG.getClientMG().cWin.FileprogressBar.setVisible(true);
ClientMG.getClientMG().cWin.FileprogressBar.setMaximum((int)filetrans.length());byte[] buff = new byte[1024];int iread = 0;int len =0;while((iread=dis.read(buff, 0, 1024))!=-1){
dos.write(buff,0, iread); //写文件是,是根据读出的大小进行写入的
len +=iread;
dos.flush();//写入流的同时,设置进度条的进度
ClientMG.getClientMG().cWin.FileprogressBar.setValue(len);
}
ClientMG.getClientMG().setLog("文件传输完毕!");
}catch(Exception e) {
e.printStackTrace();
}finally{try{
dos.close();
dis.close();if(sfile!=null){sfile.close();}if(fserver!=null){fserver.close();}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
packagerjxy.lkl.Client;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;import java.net.*;public class fileRec extendsThread{
Socket socket;
String sRecFilePath="D:\\";
String fileName;intfileLen;public fileRec(Socket socket, String fileName, intfileLen) {this.socket =socket;this.fileName =fileName;this.fileLen =fileLen;
}public voidrun() {
DataInputStream dis= null;
DataOutputStream dos= null;//设置进度条属性
ClientMG.getClientMG().cWin.FileprogressBar.setValue(0);
ClientMG.getClientMG().cWin.FileprogressBar.setVisible(true);
ClientMG.getClientMG().cWin.FileprogressBar.setMaximum(fileLen);try{
dis= newDataInputStream(socket.getInputStream());
dos= new DataOutputStream(new FileOutputStream(sRecFilePath+fileName));byte[] buff = new byte[1024];int iread = 0;int len = 0;while((iread=dis.read(buff, 0, 1024))!=-1){
dos.write(buff,0, iread);
len+=iread;
ClientMG.getClientMG().cWin.FileprogressBar.setValue(len);
dos.flush();
}
ClientMG.getClientMG().setLog("文件接收完毕!");
}catch(Exception e) {
e.printStackTrace();
}finally{try{
dis.close();
dos.close();if(socket!=null){ socket.close();}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
服务器端代码:
packagerjxy.lkl.Server;importjava.awt.BorderLayout;public class ServerForm extendsJFrame {privateJPanel contentPane;publicJPanel panel;publicJLabel label;publicJTextField txtPort;publicJButton btnStart;publicJButton btnStop;publicJScrollPane scrollPane;publicJTextArea txtLog;
ServerSocket server;
ServerListener listener;volatile booleanserverFlag;/*** Launch the application.*/
public static voidmain(String[] args) {
EventQueue.invokeLater(newRunnable() {public voidrun() {try{
ServerForm frame= newServerForm();
frame.setVisible(true);
SocketMG.getsocketMG().setServerForm(frame);//窗体对象传入SocketMG中
} catch(Exception e) {
e.printStackTrace();
}
}
});
}/*** Create the frame.*/
publicServerForm() {
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 422, 520);
contentPane= newJPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
panel= newJPanel();
panel.setBorder(new TitledBorder(null, "\u914D\u7F6E\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBounds(0, 0, 406, 66);
contentPane.add(panel);
panel.setLayout(null);
label= new JLabel("\u7AEF\u53E3\uFF1A");
label.setBounds(10, 29, 54, 15);
panel.add(label);
txtPort= newJTextField();
txtPort.setText("8899");
txtPort.setBounds(46, 21, 66, 30);
panel.add(txtPort);
txtPort.setColumns(10);
btnStart= new JButton("\u5F00\u59CB\u670D\u52A1");
btnStart.addActionListener(newBtnStartActionListener());
btnStart.setBounds(129, 21, 98, 31);
panel.add(btnStart);
btnStop= new JButton("\u505C\u6B62\u670D\u52A1");
btnStop.addActionListener(newBtnStopActionListener());
btnStop.setBounds(253, 21, 98, 31);
panel.add(btnStop);
scrollPane= newJScrollPane();
scrollPane.setBorder(new TitledBorder(null, "\u6D88\u606F\u8BB0\u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
scrollPane.setBounds(0, 76, 406, 406);
contentPane.add(scrollPane);
txtLog= newJTextArea();
scrollPane.setViewportView(txtLog);
}//启动Socket服务
private class BtnStartActionListener implementsActionListener {public voidactionPerformed(ActionEvent arg0) {int port =Integer.parseInt(txtPort.getText().trim());try{
server= newServerSocket(port);
listener= newServerListener(server);
listener.start();
SocketMG.getsocketMG().setLog("服务已开启");
}catch(Exception e) {
e.printStackTrace();
}
}
}//停止服务
private class BtnStopActionListener implementsActionListener {public voidactionPerformed(ActionEvent arg0) {
SocketMG.getsocketMG().setLog("服务器已关闭");//通知所有在线用户服务器关闭消息 交互协议为:"CLOSE|"
SocketMG.getsocketMG().sendCloseMSGToAll();//把OnlineUsers集合中的每一个SocketChat关闭
SocketMG.getsocketMG().closeALLSocket();//ArrayList清空
SocketMG.getsocketMG().clearList();//关闭ServerSocket
listener.stopListener();try{if (server != null) {
serverFlag= false;
server.close();
}
}catch(Exception e2) {//TODO: handle exception
}
}
}
}
packagerjxy.lkl.Server;importjava.io.IOException;import java.net.*;public class ServerListener extendsThread {
ServerSocket server;volatile booleanserverFlag;publicServerListener(ServerSocket server) {this.server =server;
serverFlag= true;
}//停止监听
public voidstopListener(){
serverFlag= false;
}public voidrun() {while(serverFlag){
Socket s= null;try{
s=server.accept();newSocketChat(s).start();
SocketMG.getsocketMG().setLog(s+"已登录");
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
packagerjxy.lkl.Server;import java.net.*;import java.io.*;public class SocketChat extendsThread {
Socket socket;
BufferedReader br=null;
PrintWriter pw= null;
String UserName;publicSocketChat(Socket socket) {this.socket =socket;try{
br= new BufferedReader(newInputStreamReader(socket.getInputStream(),"UTF-8"));
pw= new PrintWriter(new BufferedWriter(newOutputStreamWriter(
socket.getOutputStream(),"UTF-8")));
}catch(Exception e) {
e.printStackTrace();
}
}public voidsendMSG(String str){
pw.println(str);
pw.flush();
}//关闭SocketChat
public voidcloseChat(){try{if (socket != null)
socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}public voidrun() {try{
String str= "";while((str = br.readLine())!=null){
String comm[]= str.split("[|]");if(comm[0].equals("Login")){//读取客户端发过来的用户名
String cUsername = comm[1];//赋给服务器端的UserName
UserName =cUsername;//①得到所有在线用户发给客户端
SocketMG.getsocketMG().sendOnlineUsers(this);//②将当期的socket信息存放在OnLineUsers数组中
SocketMG.getsocketMG().addList(this);//③把当前用户信息发送给在线用户
SocketMG.getsocketMG().sendNewUsertoAll(this);
}else if(comm[0].equals("MSG")){//交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG//取出协议串中的内容
String sender = comm[1];
String receiver= comm[2];
String msg= comm[3];
System.out.println("发送者:"+sender+"---接收者:"+receiver+"---消息体:"+msg);if(receiver.equals("ALL")){//"MSG|"+sendUsername+"|ALL|"+msg
String strmsg = "MsgReturn|"+sender+"|"+msg;
SocketMG.getsocketMG().sendMSGToALL(strmsg,this);
SocketMG.getsocketMG().setLog(sender+"发消息给所有人"+"内容为:"+msg);
}else{//查询在线集合,如果接收对象则返回这个SocketChat对象
SocketChat sc =SocketMG.getsocketMG().getSocketChatByName(receiver);
System.out.println("选中的用户的信息:"+sc);if(!(sc==null)){
String strmsg= "MsgReturn"+"|"+sender+"|"+msg; //重新组织交换协议
System.out.println(strmsg);
SocketMG.getsocketMG().sendMSGToSocket(strmsg, sc);
SocketMG.getsocketMG().setLog(sender+"发送给"+sc+"的消息是:"+msg);
}
}
}else if(comm[0].equals("OFFLINE")){//用户下线的交互协议:"OFFLINE|"+username//向其他用户发送该用户下线的消息
SocketMG.getsocketMG().sendOffLineMSGToAll(this);//移除List中已经下线用户的信息
SocketMG.getsocketMG().removeList(this);
SocketMG.getsocketMG().setLog(comm[1]+"下线了");
}else if(comm[0].equals("FILETRANS")){//"FILETRANS|"+sender+"|"+sTarget+"|"+sFname+"|"+finfo.length()+"|"+IPandPort
String sender = comm[1];
SocketChat sTarget= SocketMG.getsocketMG().getSocketChatByName(comm[2]);//sFname+"|"+finfo.length()+"|"+IPandPort
String strSend = comm[3]+"|"+comm[4]+"|"+comm[5]+"|"+comm[6];//调用文件发送函数
SocketMG.getsocketMG().sendFileTrans(sender, sTarget, strSend);
SocketMG.getsocketMG().setLog(sender+"发送了"+strSend+"给"+sTarget);
}else if(comm[0].equals("FILECANCEL")){//FILECANCEL|拒收者(A)|被拒收者(B)//得到被拒收者
String A = comm[1];
SocketChat sc= SocketMG.getsocketMG().getSocketChatByName(comm[2]);//重新组织交互协议//FILECANCELReturn|拒收者A
String strSend = "FILECANCELReturn|"+A;
SocketMG.getsocketMG().setLog(A+"拒收了"+comm[2]+"传输的文件");
sc.sendMSG(strSend);
}
}
}catch(Exception e) {
e.printStackTrace();
}finally{try{if (br != null)
br.close();if (pw != null)
pw.close();if (socket != null)
socket.close();
}catch(Exception e2) {
e2.printStackTrace();
}
}
}
}
packagerjxy.lkl.Server;importjava.util.ArrayList;public classSocketMG {//实现管理类的单例化
private static final SocketMG socketMG=newSocketMG();privateSocketMG(){}public staticSocketMG getsocketMG(){returnsocketMG;
}
SocketChat sChat;//操作图形界面
ServerForm sWin;public voidsetServerForm(ServerForm s){
sWin=s;
}//设置界面中的消息记录
public voidsetLog(String str){
sWin.txtLog.append(str+"\r\n");
}//存储socket信息的集合
private ArrayList OnLineUsers = new ArrayList();//把新用户添加到集合中
public synchronized voidaddList(SocketChat sChat){
OnLineUsers.add(sChat);
}//得到所有用户在线信息名称,发回给客户端
public voidsendOnlineUsers(SocketChat sc){//发送所有用户信息的协议:USERLISTS|user1_user2_user3
if(OnLineUsers.size()>0){
String str= "";for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat sChat=OnLineUsers.get(i);
str+= sChat.UserName+"_";
}
sc.sendMSG("USERLISTS|"+str);
}
}//新上线的用户发送给所有在线用户 ADD|用户名
public voidsendNewUsertoAll(SocketChat sc){for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat socketChat=OnLineUsers.get(i);//新上线用户这个消息不发给自己,发给其他用户,让其他用户知道该你上线了
if(!socketChat.equals(sc)){
socketChat.sendMSG("ADD|"+sc.UserName);
}
}
}//通过用户名查找SocketChat对象
publicSocketChat getSocketChatByName(String name){for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat sChat=OnLineUsers.get(i);//此处曾出现过错误,形式为:sChat.equals(name)
if(sChat.UserName.equals(name)){returnsChat;
}
}return null;
}//向目标对象发送消息
public voidsendMSGToSocket(String str,SocketChat sc){
System.out.println("2222222222222"+str);
sc.sendMSG(str);
}//发送消息出自己以外的所有人
public voidsendMSGToALL(String str,SocketChat sc){for (int i = 0; i < OnLineUsers.size(); i++) {//写程序的时候遇到的问题:SocketChat sChat = OnLineUsers.get(i);//造成了与类成员变量重名,消息只发给自己
SocketChat socketChat =OnLineUsers.get(i);//if(!socketChat.equals(sc)){//socketChat.sendMSG(str);//}
socketChat.sendMSG(str);
}
}//向其他用户发送下线用户下线的通知
public voidsendOffLineMSGToAll(SocketChat sc){for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat socketChat=OnLineUsers.get(i);if(!socketChat.equals("sc")){
String str= "DEL|"+sc.UserName;
socketChat.sendMSG(str);
}
}
}//把当前下线的用户从OnLineUsers中清除
public synchronized voidremoveList(SocketChat sChat){//清除ArrayList中的当前用户信息(socketChat)
for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat schat=OnLineUsers.get(i);if(schat.equals(sChat)){
OnLineUsers.remove(sChat);break;
}
}
}//关闭服务器通知给所有在线用户
public voidsendCloseMSGToAll(){//组织交互协议为:"CLOSE|"
for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat socketchat=OnLineUsers.get(i);
socketchat.sendMSG("CLOSE|");
}
}//关闭OnlineUsers中的每一个SocketChat
public voidcloseALLSocket(){for (int i = 0; i < OnLineUsers.size(); i++) {
SocketChat socketchat=OnLineUsers.get(i);
socketchat.closeChat();
}
}//清空在线集合中的内容
public voidclearList(){
OnLineUsers.clear();
}//文件传输 发送者,接收者,内容
public voidsendFileTrans(String sender,SocketChat sTarget,String sMSG){
sTarget.sendMSG("FILETRANS|"+sender+"|"+sMSG);
}
}