Socket基于TCP协议的通信基本成了每种编程语言必须实践的一个训练项目了。本篇不普及关于Socket通信最基本的理论及简单的实现,网上有很多,并且有很好很简单的例子。本篇将列出,基于Socket网络编写chat room遇到的一些困难。
实现功能:
1. 在一个java应用程序中提供给用户选择模式:Server和Client
2. 一个Server可以同时和多个Client进行对话
3.Server端与Client可以进行自由对话(非一人一句)
问题1:单线程无法建立多个Client对话
解决方法:创建一个记录cilent socket的Arraylist,在Server端每次accept到新的client socket就将此socket,add到Arraylist里,并且在accept 到client socket连接以后,创建子线程用于处理每个不同的Client对话。
public class ServerSocketThread implements Runnable{
public void run() {
// TODO Auto-generated method stub
try{
int serverport = Integer.parseInt(portT.getText());
serversocket = new ServerSocket(serverport);
while(true){
System.out.println("ServerSocket is in server");
client = serversocket.accept();
clientlist.add(client); //add client in clientlist
ClientWorker cw = new ClientWorker(client);
new Thread(cw).start();
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
问题2:线程阻塞导致的无法轮询,接收与发送两件事。
解决方法:在server 和client中各自的子线程中只做本应该做的阻塞接收数据的工作(即DataInputStream.readUTF()),然后在主线程中更新UI界面和键盘监听事件(当敲击回车键时,发送给对方TextFiled里面的内容)。
public class WirteL implements KeyListener{
@Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getKeyChar()==KeyEvent.VK_ENTER ) //按回车键执行相应操作;
{
buf = writeT.getText();
writeT.setText("");
if(INHOST){
for(int i = 0;i < clientlist.size();i++){
try {
DataOutputStream serverout = new DataOutputStream(clientlist.get(i).getOutputStream());
serverout.writeUTF(usernameT.getText() + "said: " + buf);
serverout.flush();
showArea.append("I said: "+ buf + '\n');
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else{
try {
out.writeUTF(usernameT.getText() + "said: " + buf);
out.flush();
showArea.append("I said: "+ buf + '\n');
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
原文发于博客:http://blog.csdn.net/u013787595
GMX 2014.4.20 US Eastern Time
GMX 2014.4.20 US Eastern Time