Mybeautiful 发表于 2013-2-7 09:35:27

使用Server转发的聊天程序 (短小精悍,无重复代码, 支持多客户端)

Server 入口程序,
    仅一个类,其中 hsClientSocket用来保存所有已经连上的客户端连接,以便实现转发.
    SocketConnection这个类是封装了socket, 以便Client跟Sever都要用到的逻辑实现共用,
   MessageReceivedHandler是个接口,传给SocketConnection, 以便让SocketConnection收到消息时做具体的事情, 且可以add多个Handler.
 
 
package coc.server;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.Hashtable;import coc.client.MessageReceivedHandler;import coc.client.SocketConnection;/** * @author Stony Zhang * @E-Mail stonyz@live.com * @QQ 55279427 * @Createdate 2009-9-5 ** @Copyright the author, If you want to use the code, you must keep the author's *             information. */public class Server {private int listeningPort = 6666; // TODO: the port should be configurableServerSocket myServer = null;private Hashtable<String, SocketConnection> hsClientSocket = new Hashtable<String, SocketConnection>();public void start() {try {myServer = new ServerSocket(listeningPort);waitForConnect();} catch (IOException e) {System.out.println(e);}}private void waitForConnect() {class serverMSGHandler implements MessageReceivedHandler{private SocketConnection sc;public serverMSGHandler(SocketConnection sc){this.sc=sc;}//@Overridepublic void Message_Recived(String message) {if(message.startsWith("REGISTER:")){//regiest the Client to ServerString linkNum=message.substring("REGISTER:".length());hsClientSocket.put(linkNum, sc);sc.setLinkNum(linkNum);sc.sentMessage("Register succesfully");}else if(message.startsWith("MSGTO:")){//get the to dest Node socket, which regestered in server.    String dest=message.substring("MSGTO:".length(),"MSGTO:".length()+3);    String msgContent=message.substring(9);      SocketConnection destsc = hsClientSocket.get(dest);    if(destsc==null){    sc.sentMessage(" " +"The Node " + dest + " didn't log in.") ;    return;    }destsc.sentMessage(" " + msgContent);}else if(message.startsWith("DISCONNECT:")){String linkNum=message.substring("DISCONNECT:".length());this.sc.disconnect();hsClientSocket.remove(linkNum);}}}while (!isStop) {String clientIP = "";try {Socket sock = myServer.accept();//clientIP = sock.getInetAddress().getHostAddress();// if (checkIP(route, clientIP)) {//System.out.println(" ransfer Server : " + "" + "Incoming:"//+ sock.getInetAddress());//sock.setSoTimeout(0);//connCounter++;////Transfer myt = new Transfer(sock);//connectionQueue.add(myt);final SocketConnection sc=new SocketConnection(sock);sc.addMSGReveivedHander(new serverMSGHandler(sc));sc.start();// } else {// SysLog.warning(" ransfer Server : " + route.toString() +// "Refuse :" + sock.getInetAddress());// closeSocket(sock);// }} catch (Exception ef) {// SysLog.severe(" Transfer Server : " + route.toString() +// " accept error" + ef);}}}private boolean isStop = false;///** * @author Stony Zhang * @date Feb 22, 2009 * @param args */public static void main(String[] args) {// TODO Auto-generated method stubServer s = new Server();s.start();}} 
 
Client 入口程序
       MainGUI .java,界面类,不多解释,
package coc.client;import java.io.IOException;import org.eclipse.swt.SWT;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Group;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.MessageBox;import org.eclipse.swt.widgets.Shell;import org.eclipse.swt.widgets.Text;/** * @author Stony Zhang * @E-Mail stonyz@live.com * @QQ 55279427 * @Createdate 2009-9-5 ** @Copyright the author, If you want to use the code, you must keep the author's *             information. */public class MainGUI {private Text text_1;private Text txt_output;private Text txt_input;private Text txtServerPort;private Text txt_server;private Text text;protected Shell shell;Client c=null;/** * Launch the application * @param args */public static void main(String[] args) {try {MainGUI window = new MainGUI();window.open();} catch (Exception e) {e.printStackTrace();}}/** * Open the window */public void open() {final Display display = Display.getDefault();createContents();shell.open();shell.layout();while (!shell.isDisposed()) {if (!display.readAndDispatch())display.sleep();}c.disconnect();}/** * Create contents of the window */protected void createContents() {shell = new Shell();shell.setSize(367, 444);shell.setText("My-Connect");final Group connectGroup = new Group(shell, SWT.NONE);connectGroup.setText("Connect");connectGroup.setBounds(10, 10, 319, 66);final Label serverIpLabel = new Label(connectGroup, SWT.NONE);serverIpLabel.setText("Server IP :");serverIpLabel.setBounds(10, 20, 59, 13);txt_server = new Text(connectGroup, SWT.BORDER);txt_server.setText("192.168.254.124");txt_server.setBounds(80, 20, 95, 18);final Label serverPortLabel = new Label(connectGroup, SWT.NONE);serverPortLabel.setText("Server Port :");serverPortLabel.setBounds(181, 20, 71, 18);txtServerPort = new Text(connectGroup, SWT.BORDER);txtServerPort.setText("6666");txtServerPort.setBounds(252, 20, 49, 18);final Label linkNumberLabel = new Label(connectGroup, SWT.NONE);linkNumberLabel.setBounds(10, 40,69, 18);linkNumberLabel.setText("Link Number :");text = new Text(connectGroup, SWT.BORDER);text.setBounds(80, 41,59, 18);final Button connectButton = new Button(connectGroup, SWT.NONE);connectButton.addSelectionListener(new SelectionAdapter() {public void widgetSelected(final SelectionEvent e) {if(connectButton.getText().equalsIgnoreCase("connect")){String name=txt_server.getText().trim();String port=txtServerPort.getText().trim();String linkNum=text.getText().trim();linkNum="000" + linkNum;linkNum=linkNum.substring(linkNum.length()-3);text.setText(linkNum);c=new Client(name,port,linkNum);c.connect(new MessageReceivedHandler(){//@Overridepublic void Message_Recived(String message) {updateSwtGui(message);////FIXME, auto replay//StringBuffer msg=new StringBuffer();//msg.append("MSGTO:").append("022");//msg.append("Receieved, it's OK");////try {//c.sentMessage(msg.toString());//} catch (IOException e) {//// TODO Auto-generated catch block//e.printStackTrace();//}//---------------------------}});}else{c.disconnect();c=null;}if(connectButton.getText().equalsIgnoreCase("connect")){connectButton.setText("disconnect");}else{connectButton.setText("connect");}}});connectButton.setText("Connect");connectButton.setBounds(240, 40, 61, 23);txt_input = new Text(shell, SWT.BORDER|SWT.MULTI | SWT.WRAP);txt_input.setBounds(10, 104, 319, 92);//txt_input.settxt_output = new Text(shell, SWT.BORDER|SWT.MULTI | SWT.WRAP);txt_output.setBounds(10, 224, 319, 164);final Label inputLabel = new Label(shell, SWT.NONE);inputLabel.setText("Send To :");inputLabel.setBounds(10, 85, 46, 13);final Label outputLabel = new Label(shell, SWT.NONE);outputLabel.setText("Output :");outputLabel.setBounds(10, 205, 46, 13);final Label lbl_status = new Label(shell, SWT.NONE);lbl_status.setBounds(10, 394, 319, 13);text_1 = new Text(shell, SWT.BORDER);text_1.setBounds(88, 82, 65, 16);final Button sendButton = new Button(shell, SWT.NONE);sendButton.addSelectionListener(new SelectionAdapter() {public void widgetSelected(final SelectionEvent e) {if (c == null) {MessageBox messageBox = new MessageBox(shell, SWT.OK);messageBox.setMessage("Please connect to server firstly");if (messageBox.open() == SWT.OK) {return;}}String to=text_1.getText().trim();StringBuffer msg=new StringBuffer();msg.append("MSGTO:").append(to);msg.append(txt_input.getText().trim());try {c.sentMessage(msg.toString());} catch (IOException e1) {e1.printStackTrace();}txt_input.setText("");}});sendButton.setText("Send");sendButton.setBounds(260, 80, 44, 23);//}private synchronized void updateSwtGui(final String output) {shell.getDisplay().asyncExec( // where "display" represents the swt gui// thread accessed asynchronouslynew Runnable() {public void run() {txt_output.append(output + "\n");}});}} 
Client.java, 客户端业务类
 
 
package coc.client;import java.io.IOException;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;/** * @author Stony Zhang * @E-Mail stonyz@live.com * @QQ 55279427 * @Createdate 2009-9-5 ** @Copyright the author, If you want to use the code, you must keep the author's *             information. */public class Client {String name;String ip;String port;String linkNum;Socket socket = null;//DataOutputStream os = null;//DataInputStream is = null;//TODO; server ip and port should be configurable.String serverIP = "192.168.254.124";int ServerPort=6666;private MessageReceivedHandler defaultHandle = new MessageReceivedHandler(){//@Overridepublic void Message_Recived(String message) {// TODO Auto-generated method stubString host="";String linkNum="";System.out.print("Recieve message from " + host + " linkNum =" + host + " : " + message);}};public Client(String name,String port,String linkNum){//this.name=name;this.serverIP=name;this.linkNum=linkNum;this.port=port;try {InetAddress IPAddress = InetAddress.getByName("localhost");this.ip=IPAddress.getHostAddress();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} }public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public String getPort() {return port;}public void setPort(String port) {this.port = port;}public void sentMessage(String msg) throws IOException{sc.sentMessage(msg);}public String recieveMessage(){return null;}public void connect(MessageReceivedHandler handle){try {socket = new Socket(this.serverIP, this.ServerPort);sc = new SocketConnection(socket);sc.addMSGReveivedHander(handle);sc.start();sc.sentMessage("REGISTER:" + this.linkNum);//startListenMessage();} catch (UnknownHostException e) {System.err.println("Don't know about host: hostname");} catch (IOException e) {System.err.println("Couldn't get I/O for the connection to: hostname");}}public void disconnect(){sc.sentMessage("DISCONNECT:");sc.disconnect();}SocketConnection sc;public static void main(String[] argv){String name=argv;String port=argv;String linkNum=argv;Client c=new Client(name,port,linkNum);c.connect(c.defaultHandle);try {c.sentMessage("MSGTO:002 Are you ok?");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} 
MessageReceiverdHandler.java  传给 SocketConnection类的Handler,作用前面已经说了, 具体实现在Client.java, Server.java各有一个。
 
 
package coc.client;/** * @author Stony Zhang * @E-Mail stonyz@live.com * @QQ 55279427 * @Createdate 2009-9-5 ** @Copyright the author, If you want to use the code, you must keep the author's *             information. */public interface MessageReceivedHandler {void Message_Recived(String message);} 
   SocketConnection.java  封装socket, 扩展了一些功能。
 
 
package coc.client;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.util.ArrayList;import java.util.List;/** * @author Stony Zhang * @E-Mail stonyz@live.com * @QQ 55279427 * @Createdate 2009-9-5 ** @Copyright the author, If you want to use the code, you must keep the author's *             information. */public class SocketConnection {Socket socket = null;DataOutputStream os = null;DataInputStream is = null;public SocketConnection(Socket socket){this.socket=socket;try {os = new DataOutputStream(socket.getOutputStream());is = new DataInputStream(socket.getInputStream());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void start(){startListenMessage();}class MessageReader{List<MessageReceivedHandler> handlers=new ArrayList<MessageReceivedHandler>();Thread t=new Thread(){public void run(){try {String responseLine;while ((responseLine = is.readLine()) != null) {//System.out.println("Server: " + responseLine);for (MessageReceivedHandler h : handlers) {h.Message_Recived(responseLine);}if (responseLine.indexOf("Ok") != -1) {break;}}} catch (IOException e) {e.printStackTrace();}System.out.print("Message Reader exit");}};public void start(){t.start();}public void addHander(MessageReceivedHandler Handle) {handlers.add(Handle);}}MessageReader reader=new MessageReader();private void startListenMessage() {//reader.addHander(this.defaultHandle);reader.start();}public void addMSGReveivedHander(MessageReceivedHandler Handle){reader.addHander(Handle);}public void sentMessage(String msg){try {os.writeBytes(msg + "\n");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private String linkNum="";public void setLinkNum(String linkNum) {this.linkNum=linkNum;}public String getLinkNum() {return linkNum;}public void disconnect() {try {is.close();os.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}     客户端运行如图,
       002 说 Are you ok?
       001 说 I'm fine Thank you!

http://dl.iteye.com/upload/attachment/244433/1fe206b3-61b0-3eb7-bc4a-d5e2b649348b.png
 
    完整 eclipse工程下载,下载..
 
页: [1]
查看完整版本: 使用Server转发的聊天程序 (短小精悍,无重复代码, 支持多客户端)