0%

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){
                
            }

    }
}