Java中的Socket.、线程和HaspMap的使用

Java中的Socket.、线程和HaspMap的使用

 

程序的功能:实现多人聊天

关键技术点说明:服务器将每个客户端的线程保存在hashmap中,这样就能实现数据正确转发到哪个窗口。客户端这边将连接服务器的线程也保存起来,同时还要保存线程对应的聊天界面,这样通过读取连接服务器的线程就能正确收到消息,通过线程对应的界面就能将消息正确的显示。通过这个实例熟悉一下面向对象编程。

程序关键代码实现:

服务端:

1.服务器建立ServerSocket 

public class MyQqServer {

public MyQqServer()

{

try {

ServerSocket ss=new ServerSocket(3456);

while(true)

{

Socket s=ss.accept();

ObjectInputStream ois=new ObjectInputStream(s.getInputStream());

User u=(User)ois.readObject();

Message m=new Message();

ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());

if(u.getPasswd().equals("12"))

{

m.setMessType("1");

oos.writeObject(m);

SerConClientThread scct=new SerConClientThread(s);

ManageClientThread.addClientThread(u.getUserid(), scct);

scct.start();

scct.notifyother(u.getUserid());

}else 

{

m.setMessType("2");

oos.writeObject(m);

s.close();

}

  }

} catch (Exception e) {

// TODO: handle exception

}finally{

}

}

 

2.将客户端的线程放进HashMap

public class ManageClientThread {

public static HashMap<String, SerConClientThread> hm=new HashMap<String,SerConClientThread>();

public static void addClientThread(String uid,SerConClientThread ct)

{

hm.put(uid, ct);

}

public static SerConClientThread getClientThread(String uid)

{

return (SerConClientThread)hm.get(uid);

}

public static String getAllOnLineUserid()

{

Iterator<String> it=hm.keySet().iterator();

String res="";//问题所在 “ ” 这个是错的

while(it.hasNext())

{

res+=it.next().toString()+" ";

}

return res;

}

}

 

3.当有一个客户端连接进来的时候就创建一个线程

public class SerConClientThread extends Thread{

Socket s;

public SerConClientThread(Socket s){

//把服务器和该客户端的连接赋给s

this.s=s;

}

//让该线程去通知其他用户

public void notifyother(String iam)

{

HashMap<String, SerConClientThread> hm=ManageClientThread.hm;

Iterator<String> it=hm.keySet().iterator();

while(it.hasNext())

{

Message m=new Message();

m.setCon(iam);

m.setMessType(MessageType.message_ret_onLineFriend);

String onLineUserId=it.next().toString();

try {

ObjectOutputStream oos=new ObjectOutputStream(ManageClientThread.getClientThread(onLineUserId).s.getOutputStream());

m.setGetter(onLineUserId);

oos.writeObject(m);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

}

public void run(){

while(true){

try {

ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

Message m = (Message) ois.readObject();

if(m.getMessType().equals(MessageType.message_comm_mes))

{

//取得接收人的线程  实现转发    ( SerConClientThread是连接的线程 在MyQqServer时候被创建)

SerConClientThread sc=ManageClientThread.getClientThread(m.getGetter());

ObjectOutputStream oos=new ObjectOutputStream(sc.s.getOutputStream());

oos.writeObject(m);

}else if(m.getMessType().equals(MessageType.message_get_onLineFriend))

{

//把在服务器的好友返回给该客户端

String res=ManageClientThread.getAllOnLineUserid();

Message m1=new Message();

m1.setMessType(MessageType.message_ret_onLineFriend);

m1.setCon(res);

m1.setGetter(m.getSender());//服务端发给客服端,客户端是getter, sengder是客户端发的

ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());

oos.writeObject(m1);

}

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

}

 

}

客户端:

1客户端与服务器的线程放在HashMap,保持聊天界面中是将线程对应的界面放进HashMap

public class ManageClientConServerThread {

private static HashMap<String, ClientConServerThread> hm=new HashMap<String,ClientConServerThread>();

//把创建好的ClientConServerThread放入到hm

public static void addClientConServerThread(String qqId,ClientConServerThread ccst)

{

hm.put(qqId, ccst);

}

//可以通过qqId取得该线程 

public static ClientConServerThread getClientConServerThread(String qqId)

{

return (ClientConServerThread)hm.get(qqId);

}

}

2.这是客户端接收服务器消息在线程中的实现代码

public class ClientConServerThread extends Thread{

private Socket s;

public Socket getS() {

return s; 

}

public void setS(Socket s) {

this.s = s;

}

public ClientConServerThread(Socket s){

this.s=s;

}

public void run(){

while(true)

{

try {

//不停的读取从服务器端发来的消息

ObjectInputStream ois = new ObjectInputStream(s.getInputStream());

Message m = (Message) ois.readObject();

// System.out.println("读取到从服务发来的消息"+ m.getSender() +" 给 "+m.getGetter()+" 内容"+m.getCon());

//把从服务器获得的消息,显示到该显示的聊天界面

if(m.getMessType().equals(MessageType.message_comm_mes))

{

QqChat qqChat=ManageQqChat.getQqChat(m.getGetter()+" "+m.getSender());//这边是接收 ,所以getGetterlogin自己

qqChat.showMessage(m);

}else if(m.getMessType().equals(MessageType.message_ret_onLineFriend)){

System.out.println("客户端接收到的信息"+m.getCon());

String con=m.getCon();

String friends[]=con.split(" ");

String getter=m.getGetter();//返回给发送者, 就是要得到好友列表的send

//修改相应的好友列表

QqFriendList qqFriendList=ManageQqFriendList.getQqFriendList(getter);

//更新好友类表

if(qqFriendList!=null){

qqFriendList.updataFriend(m);

}

}

} catch (Exception e) {

e.printStackTrace();

// TODO: handle exception

}

}

}

 

}

3.客户端连接服务器的实现

public class QqClientConServer {

public Socket s;

public boolean  sendLoginInfoToServer(Object o)

{

boolean b=false;

try{

s = new Socket("211.80.180.73", 3456);

ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());

oos.writeObject(o);

System.out.print(o);

System.out.println("客服端发送成功");

ObjectInputStream ois=new ObjectInputStream(s.getInputStream());

Message ms=(Message)ois.readObject();

System.out.println("收到的信息类型"+ms.getMessType());

if(ms.getMessType().equals("1"))

{

//就创建一个该qq号和服务器保持通讯的连接线程

ClientConServerThread ccst=new ClientConServerThread(s);

// ManageClientConServerThread d=new ManageClientConServerThread();

// d.addClientConServerThread(((User)o).getUserid(), ccst);//证明了是STATIC 可以直接用  在编译时已经实例化

ManageClientConServerThread.addClientConServerThread(((User)o).getUserid(), ccst);

ccst.start();

b=true;

}else{

// s.close();

}

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}finally{

}

return b;

}

/

未完成:好多

计划:计算器

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值