今天学习下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){
}
}
}