?? chatserver.java
字號:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class chatServer extends JFrame {
//以下為圖形界面變量
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenuFile = new JMenu();
JMenuItem jMenuFileExit = new JMenuItem();
JMenu jMenuHelp = new JMenu();
JMenuItem jMenuHelpAbout = new JMenuItem();
JLabel statusBar = new JLabel();
BorderLayout borderLayout1 = new BorderLayout();
JPanel jPanel1 = new JPanel();
BorderLayout borderLayout2 = new BorderLayout();
JLabel jLabel1 = new JLabel();
static java.awt.List jList1 = new java.awt.List(13);
JScrollPane scrollpane=new JScrollPane(jList1);
//以下為網(wǎng)絡(luò)相關(guān)變量
static Vector clients=new Vector(10); //用vector向量數(shù)組存儲連接客戶變量
static ServerSocket server=null; //建立服務(wù)器socket
static int active_connects=0; //用來存儲目前連接的客戶數(shù)
static Socket socket=null; //用來存儲一個套接字連接
//chatServer main method
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
chatServer chatServer1=new chatServer(); //實例化一個chatServer類
chatServer1.show();
System.out.println("Server starting ...");
try
{
server=new ServerSocket(2525); //使用端口2525初始化服務(wù)器套接字
}
catch(IOException e)
{
System.out.println("Error:"+e);
}
while(true)
{
if(clients.size()<5) //當客戶數(shù)小于5個時開始連接
{
try
{
socket=server.accept(); //用來存儲連接上的客戶socket
if(socket!=null)
{
System.out.println(socket+"連接"); //在控制臺打印客戶連接信息
}
}
catch(IOException e)
{
System.out.println("Error:"+e);
}
int i=0;
do{
Client c=new Client(socket); //定義并實例化一個Client線程類,一個就對應一個客戶連接
clients.addElement(c); //加入clients數(shù)組中
if(checkName(c)) //調(diào)用checkName方法驗證c的合法性
{
int connum=++chatServer1.active_connects; //定義connum來存儲活動連接數(shù)
String constr="目前有"+connum+"客戶相連"; //在狀態(tài)欄里顯示連接數(shù)
chatServer1.statusBar.setText(constr);
Client listdata=(Client)clients.elementAt(i); //將連接客戶的socket信息存儲進listdata數(shù)組
chatServer1.jList1.addItem(listdata.ip+"連接",i); //將客戶socket信息寫入list框
c.start(); //啟動線程
notifyRoom(); //用notifyRoom方法來監(jiān)視聊天室連接變化
//不斷改變clients數(shù)組并刷新客戶端信息
}
else
{
//如果名字不合法
c.ps.println("TAKEN");
disconnect(c);
}
i++;
break;
}
while(i<clients.size());
}
else //如果clients數(shù)組超過了5個
{
try{Thread.sleep(200);}
catch(InterruptedException e)
{
}
}
}//end of while
}// end of main method
/**Construct the frame*/
public chatServer() //chatServer類的構(gòu)造器用來初始化一些UI信息
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Component initialization*/
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Your Icon]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("簡易聊天服務(wù)器端");
statusBar.setText("目前的連接數(shù)為:");
jMenuFile.setText("File");
jMenuFileExit.setText("Exit");
jMenuFileExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuFileExit_actionPerformed(e);
}
});
jMenuHelp.setText("Help");
jMenuHelpAbout.setText("About");
jMenuHelpAbout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuHelpAbout_actionPerformed(e);
}
});
jPanel1.setLayout(borderLayout2);
jLabel1.setText("服務(wù)器端連接客戶");
jMenuFile.add(jMenuFileExit);
jMenuHelp.add(jMenuHelpAbout);
jMenuBar1.add(jMenuFile);
jMenuBar1.add(jMenuHelp);
this.setJMenuBar(jMenuBar1);
contentPane.add(statusBar, BorderLayout.SOUTH);
contentPane.add(jPanel1, BorderLayout.CENTER);
jPanel1.add(jLabel1, BorderLayout.NORTH);
jPanel1.add(scrollpane, BorderLayout.CENTER);
}//end of jbinit
/**File | Exit action performed*/
public void jMenuFileExit_actionPerformed(ActionEvent e) //實現(xiàn)退出菜單方法
{
sendClients(new StringBuffer("QUIT")); //向客戶端發(fā)送斷開連接信息
closeAll(); //調(diào)用closeAll方法關(guān)閉所有連接
System.exit(0);
}
/**Help | About action performed*/
public void jMenuHelpAbout_actionPerformed(ActionEvent e) //實現(xiàn)about對話框,意義不大,可以去掉
{
chatServer_AboutBox dlg = new chatServer_AboutBox(this);
Dimension dlgSize = dlg.getPreferredSize();
Dimension frmSize = getSize();
Point loc = getLocation();
dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
dlg.setModal(true);
dlg.show();
}
/**Overridden so we can exit when window is closed*/
protected void processWindowEvent(WindowEvent e) //實現(xiàn)關(guān)閉服務(wù)器程序要進行的操作
{
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
jMenuFileExit_actionPerformed(null);
}
}
/*以下實現(xiàn)各種方法*/
public static void notifyRoom() //用來監(jiān)視連接信息,不斷刷新clients數(shù)組并刷新客戶端用戶列表信息
{
StringBuffer people=new StringBuffer("PEOPLE");
for(int i=0;i<clients.size();i++)
{
Client c=(Client)clients.elementAt(i);
people.append(":"+c.name);
}
sendClients(people); //用sendClients方法向客戶端發(fā)送信息
}
public static synchronized void sendClients(StringBuffer msg) //實現(xiàn)sendClients方法專用來向每個連接的客戶端發(fā)送信息
{
for(int i=0;i<clients.size();i++)
{
Client c=(Client)clients.elementAt(i);
c.send(msg);
}
}
public static void closeAll() //實現(xiàn)關(guān)閉所有連接信息
{
while(clients.size()>0) //遍歷clients數(shù)組刪除所有連接客戶信息
{
Client c=(Client)clients.firstElement();
try
{
c.socket.close();
}
catch(IOException e)
{
System.out.println("Error:"+e);
}
finally
{
clients.removeElement(c);
}
}//end of while
}//end of closeAll method
public static boolean checkName(Client newclient) //實現(xiàn)檢查連接客戶的socket信息是否合法
{
for(int i=0;i<clients.size();i++)
{
Client c=(Client)clients.elementAt(i);
if((c!=newclient)&&c.equals(newclient.name))
return false;
}
return(true);
}//end of checkName method
public static synchronized void disconnect(Client c) //實現(xiàn)斷開單個客戶的方法
{
try
{
jList1.addItem(c.ip+"斷開連接"); //在服務(wù)器端程序的list框中顯示斷開信息
chatServer.active_connects--; //將連接數(shù)減1
c.send(new StringBuffer("QUIT")); //向客戶發(fā)送斷開連接信息
c.socket.close();
}
catch(IOException e)
{
System.out.println("Error:"+e);
}
finally
{
clients.removeElement(c); //從clients數(shù)組中刪除此客戶的相關(guān)socket等信息
}
}
}
class Client extends Thread //實現(xiàn) Client線程類
{
Socket socket; //用來存儲一個連接客戶的socket信息
String name; //用來存儲客戶的連接姓名
String ip; //用來存儲客戶的ip信息
DataInputStream dis; //用來實現(xiàn)接受從客戶端發(fā)來的數(shù)據(jù)流
PrintStream ps; //用來實現(xiàn)向客戶端發(fā)送信息的打印流
public void send(StringBuffer msg) //實現(xiàn)想客戶端發(fā)送信息的方法
{
ps.println(msg); //用打印流發(fā)送信息
ps.flush();
}
public Client(Socket s) //Client線程類的構(gòu)造器
{
socket=s;
try
{
dis=new DataInputStream(s.getInputStream()); //存儲特定客戶socket的輸入流接受s這個客戶發(fā)送到服務(wù)器端的信息
ps=new PrintStream(s.getOutputStream()); //存儲特定客戶socket的輸出流發(fā)送服務(wù)器給s這個客戶的信息
String info=dis.readLine(); //讀取接受來的信息
StringTokenizer stinfo=new StringTokenizer(info,":"); //用StringTokenizer類來讀取用":"分段字符
String head=stinfo.nextToken(); //head用來存儲類似于關(guān)鍵字的頭信息
if(stinfo.hasMoreTokens())
name=stinfo.nextToken(); //關(guān)鍵字后的第二段數(shù)據(jù)是客戶名信息
if(stinfo.hasMoreTokens())
ip=stinfo.nextToken(); //關(guān)鍵字后的第三段數(shù)據(jù)是客戶ip信息
System.out.println(head); //在控制臺打印頭信息
}
catch(IOException e)
{
System.out.println("Error:"+e);
}
}//end of Client constrator
public void run() //線程運行方法
{
while(true)
{
String line=null;
try
{
line=dis.readLine(); //讀取客戶端發(fā)來的數(shù)據(jù)流
}
catch(IOException e)
{
System.out.println("Error"+e);
chatServer.disconnect(this);
chatServer.notifyRoom();
return;
}
if(line==null) //客戶已離開
{
chatServer.disconnect(this);
chatServer.notifyRoom();
return;
}
StringTokenizer st=new StringTokenizer(line,":");
String keyword=st.nextToken();
if(keyword.equals("MSG")) //如果關(guān)鍵字是MSG則是客戶端發(fā)來的聊天信息
{
StringBuffer msg=new StringBuffer("MSG:"); //在服務(wù)器端再重新建立一個字符緩沖
msg.append(name);
msg.append(st.nextToken("\0"));
chatServer.sendClients(msg); //再將某個客戶發(fā)來的聊天信息發(fā)送到每個連接客戶的聊天欄中
}
else if(keyword.equals("QUIT")) //如果關(guān)鍵字是QUIT則是客戶端發(fā)來斷開連接的信息
{
chatServer.disconnect(this); //服務(wù)器斷開與這個客戶的連接
chatServer.notifyRoom(); //繼續(xù)監(jiān)聽聊天室并刷新其他客戶的聊天人名list
this.stop();
}
}
}
} //end of class Client
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -