Java Socket编程 服务端与客户端通讯 基于SWT

今天学习下Java的Socket编程.为了演示效果更直观,用SWT加了UI,说实话,SWT相当好用,用Eclipse的WindowBuilder插件,可以实现可视化编程,基本上不用学习,再加上SWT跟我们的移动开发没什么关系,所以这部分不解释.今天的例子是一个不完整的聊天室,说它不完整是因为我只是拿它演示客户端与服务器之间的通讯,并没有加入多客户端聊天的功能.上个效果图:


客户端源代码:


package com.pocketdigi;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import org.eclipse.jface.dialogs.MessageDialog;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class ChatClient {


	public static void main(String[] args) throws UnknownHostException, IOException {
		Display display = Display.getDefault();
		final Shell shlClient = new Shell();
		shlClient.setSize(563, 406);
		shlClient.setText("Client");
		
		final Text showMsg = new Text(shlClient, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI);
		showMsg.setEditable(false);
		showMsg.setBounds(10, 10, 527, 243);

		
		final Text name = new Text(shlClient, SWT.BORDER);
		name.setBounds(58, 267, 129, 23);
		
		Label label = new Label(shlClient, SWT.NONE);
		label.setBounds(10, 270, 61, 17);
		label.setText("姓名:");
		
		Label lblNewLabel = new Label(shlClient, SWT.NONE);
		lblNewLabel.setBounds(10, 321, 43, 17);
		lblNewLabel.setText("信息:");
		
		final Text msg = new Text(shlClient, SWT.BORDER);
		msg.setBounds(55, 321, 386, 23);
		
		
		
		Button btnSend = new Button(shlClient, SWT.NONE);
		btnSend.setBounds(447, 321, 80, 27);
		btnSend.setText("发送");
		
		btnSend.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				String nameText=name.getText();
				String msgText=msg.getText();
				//拿到姓名和信息的string
				if(!nameText.equals("")&&!msgText.equals("")){
					msg.setText("");
					try {
						Socket s=new Socket(InetAddress.getByName(null),5555);
						//连接服务器,后面参数null,就是localhost,服务器不在本机改成IP
						OutputStream os=s.getOutputStream();
						ObjectOutputStream oos=new ObjectOutputStream(os);
						MessageData md=new MessageData(nameText,msgText);
						//封装一下,比较好处理
						oos.writeObject(md);
						//发送数据给服务器
						
						ObjectInputStream ois = new ObjectInputStream(
								s.getInputStream());
						md = (MessageData) ois.readObject();
						//接收服务器返回
						showMsg.append(md.name+"说:\n");
						showMsg.append(md.msg+"\n");
						//显示在上面的Text框中
						
						oos.close();
						ois.close();
						s.close();
						//关闭流
					} catch (Exception e1) {
						// TODO Auto-generated catch block
						MessageDialog.openError(shlClient, "发送失败", "信息发送失败");
						e1.printStackTrace();
					}
				}
			}
		});


		shlClient.open();
		shlClient.layout();
		while (!shlClient.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
}
class MessageData implements Serializable{
	String name;
	String msg;
	MessageData(String name,String msg){
		this.name=name;
		this.msg=msg;
	}
	@Override
	public String toString() {
		return "MessageData [msg=" + msg + ", name=" + name + "]";
	}
}

服务器端:


package com.pocketdigi;

import java.io.IOException;

public class Server {

	/**
	 * Launch the application.
	 * 
	 * @param args
	 * @throws IOException
	 */
	static ServerSocket ss;
	static boolean stopFlag = false;

	public static void main(String[] args) throws IOException {
		Display display = Display.getDefault();
		Shell shlChatServer = new Shell();
		shlChatServer.setSize(368, 244);
		shlChatServer.setText("Chat Server");

		final Button stop = new Button(shlChatServer, SWT.NONE);
		stop.setBounds(186, 58, 95, 48);
		stop.setText("关闭服务器");
		
		final Button start = new Button(shlChatServer, SWT.NONE);
		start.setBounds(48, 58, 95, 48);
		start.setText("开启服务器");
		
		start.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				//开启按钮
				stopFlag = false;
				start.setEnabled(false);
				stop.setEnabled(true);
				//设置按钮是否可用
				try {
					ss = new ServerSocket(5555);
					//监听端口5555
					new Thread(){
						public void run(){
							while (!stopFlag) {
								Socket s;
								try {
									s = ss.accept();
									//接受客户端连接
									new ServerThread(s).start();
									//收到连接后开启新线程给客户端服务
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
						}
					}.start();

				} catch (IOException e3) {
					// TODO Auto-generated catch block
					e3.printStackTrace();
				}

			}
		});


		stop.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				//关闭服务器按钮
				stopFlag = true;
				stop.setEnabled(false);
				start.setEnabled(true);
				try {
					ss.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

			}
		});


		shlChatServer.open();
		shlChatServer.layout();
		while (!shlChatServer.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		//SWT的内容,不解释
	}


}
class ServerThread extends Thread{
	Socket s;
	ServerThread(Socket s){
		this.s=s;
	}
	public void run(){
		try{
			OutputStream os = s.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(
					os);

			InputStream is = s.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(
					is);
			//以上顺利不可倒,必须先out,再in,否则可能出现死锁,服务器跟客户端都等待对方发送数据
			MessageData md = (MessageData) ois.readObject();
			//得到客户端发送的数据
			System.out.println(md);

			oos.writeObject(md);
			//发回给客户端
			oos.close();
			ois.close();
			s.close();
			//关闭流
			}catch(Exception e){
				
			}

	}
}

© 2011, 冰冻鱼. 请尊重作者劳动成果,复制转载保留本站链接! 应用开发笔记