使用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 configurable
	ServerSocket 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;
			}
			

//			@Override
			public void Message_Recived(String message) {

				if(message.startsWith("REGISTER:")){
					//regiest the Client to Server
					String 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("[From :Server ] " +"The Node " + dest + " didn't log in.") ;
				    	return;
				    }
						destsc.sentMessage("[From :" + sc.getLinkNum()+ "] " + 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 stub
		Server 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(){

//						@Override
						public 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.set

		txt_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 asynchronously
				new 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(){

//		@Override
		public void Message_Recived(String message) {
			// TODO Auto-generated method stub
			String 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 block
			e.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[0];
		String port=argv[1];
		String linkNum=argv[2];
		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 block
			e.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 block
			e.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 block
			e.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!


 

    完整 eclipse工程下载,下载..

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值