打赏

JAVA入门到精通-网络编程补充和QQ案例

------------------------------------------------------

补充讲解:

如何在网络间传递对象?

[MyServer.java]服务器源代码

39
39
 
1
package com.test.server;
2
import java.io.ObjectInputStream;
3
import java.net.ServerSocket;
4
import java.net.Socket;
5
import com.common.User;
6
 
7
public class MyServer {
8
    ServerSocket ss;
9
    Socket s;
10
    ObjectInputStream ois;
11
   
12
    public static void main(String[] args) {
13
        new MyServer();
14
    }
15
   
16
    //构造函数
17
    public MyServer(){
18
        try {
19
            ss=new ServerSocket(3456);
20
            s=ss.accept();
21
            //以对象流的方式读取(假设客户端发送的是User的一个对象)
22
            ois=new ObjectInputStream(s.getInputStream());
23
            User u=(User)ois.readObject();
24
            //输出
25
            System.out.println(u.getName()+"\t"+u.getPasswd());
26
           
27
        } catch (Exception e) {
28
            e.printStackTrace();
29
        }finally{
30
            try {
31
                if(ois!=null) ois.close();
32
                if(s!=null) s.close();
33
                if(ss!=null) ss.close();
34
            } catch (Exception e2) {
35
                e2.printStackTrace();
36
            }
37
        }
38
    }
39
}

[User.java]服务端的公共服务

20
20
 
1
package com.common;
2
 
3
import java.io.Serializable;
4
 
5
public class User implements Serializable{
6
    private String name;
7
    private String passwd;
8
    public String getName() {
9
        return name;
10
    }
11
    public void setName(String name) {
12
        this.name = name;
13
    }
14
    public String getPasswd() {
15
        return passwd;
16
    }
17
    public void setPasswd(String passwd) {
18
        this.passwd = passwd;
19
    }
20
}

 

[MyClient.java]客户端源代码

36
36
 
1
package com.test.client;
2
 
3
import java.io.ObjectOutputStream;
4
import java.net.Socket;
5
import com.common.User;
6
 
7
public class MyClient {
8
    Socket s;
9
    ObjectOutputStream oos;
10
   
11
    public static void main(String[] args) {
12
        new MyClient();
13
    }
14
 
15
    //构造函数
16
    public MyClient(){
17
        try {
18
            s=new Socket("127.0.0.1",3456);
19
            //通过ObjectOutputStream给服务器传送对象
20
            oos=new ObjectOutputStream(s.getOutputStream());
21
            User u=new User();
22
            u.setName("张三");
23
            u.setPasswd("123");
24
            oos.writeObject(u);
25
        } catch (Exception e) {
26
            e.printStackTrace();
27
        }finally{
28
            try {
29
                if(oos!=null) oos.close();
30
                if(s!=null) s.close();
31
            } catch (Exception e2) {
32
                e2.printStackTrace();
33
            }
34
        }
35
    }
36
}

 

[User.java]客户端的公共服务

21
 
1
package com.common;
2
 
3
import java.io.Serializable;
4
//通过io在网络上传送对象需要进行序列化Serializable
5
public class User implements Serializable{
6
    private String name;
7
    private String passwd;
8
   
9
    public String getName() {
10
        return name;
11
    }
12
    public void setName(String name) {
13
        this.name = name;
14
    }
15
    public String getPasswd() {
16
        return passwd;
17
    }
18
    public void setPasswd(String passwd) {
19
        this.passwd = passwd;
20
    }
21
}

特别说明:

java网络编程需要通过IO流实现对象的传递需要对,服务端和客户端定义相同的传递对对向方法,以达到实现对象的传递。同时需要对方法进行Serializable序列化,否则报错。


------------------------------


QQ
案例

说明:该案例主讲内容:java网络编程、多线程、C/S数据交互

附源代码

注:代码分为Server部分与Client部分,由于此案例仅为对NET操作未使用数据库

Server部分包含的包有:

1、com.qq.server.view (服务端界面包)

1.1QqServerFrame.java (服务端主页面)

2、com.qq.server.model (业务逻辑包)

2.1MyQqServer.java (服务器验证客户信息)

2.2QqServerUser.java (用于管理QQ用户信息[此包功能应为对数据库逻辑操作])()

2.3SerConClientThread.java (服务器连接客户端线程)

2.4ManageClientThrea.java (管理客户端连接线程)

3com.qq.server.db (数据库操作包)

   3.1SqlHelper.java (对数据库的CURD操作)()

4com.qq.server.tools (服务端工具包)()

5com.qq.common (通用包)

   5.1Message.java (消息类)

   5.2MessageType.java (消息类型接口类)

   5.3User.java (用户信息类)

Client部分包含的包有:

1、com.qq.client.view (客户端界面包)

1.1、QqClientLogin.java (QQ登录界面)

1.2、QqFriendList.java (好友列表界面)

1.3、QqChat.java (聊天界面)

2、com.qq.client.model (客户端业务逻辑包)

2.1QqClienConServer.java (客户端连接服务端的后台用于与服务端数据交互)

2.2QqClientUser.java (客户端用户操作逻辑类)

3com.qq.client.tools (原应为客户端工具包,现为处理与服务端的线程包)

   3.1ClientConServerThread.java (客户端连接服务器线程类)

   3.2ManageClientConServerThread.java (管理C/S线程类)

   3.3ManageQqChat.java (管理聊天界面类)

   3.4ManageQqFriendList.java (管理好友列表类)

4com.qq.common (通用包)

   4.1Message.java (消息类)

   4.2MessageType.java(消息类型类)

   4.3User.java (用户信息类)

注意:ServerClient中的com.qq.common通用包主要功能是统一保持客户端与服务端的用户及消息一致。

 

下见源代码:

 

 

Server端源代码:

com.qq.server.view

[QqServerFrame.java]

48
 
1
/**
2
 * 服务器端的控制界面
3
 * 功能:
4
 *     1、完成启动、关闭服务器
5
 *     2、管理及监控用户
6
 */
7
package com.qq.server.view;
8
 
9
import java.awt.event.ActionEvent;
10
import java.awt.event.ActionListener;
11
import javax.swing.JButton;
12
import javax.swing.JFrame;
13
import javax.swing.JPanel;
14
import com.qq.server.model.MyQqServer;
15
 
16
public class QqServerFrame extends JFrame implements ActionListener{
17
    JPanel jp1;
18
    JButton jb1,jb2;
19
   
20
    public static void main(String []args){
21
        new QqServerFrame();
22
    }
23
   
24
    //构造函数
25
    public QqServerFrame(){
26
        jp1=new JPanel();
27
        jb1=new JButton("启动服务器");
28
        jb1.addActionListener(this);
29
        jb2=new JButton("关闭服务器");
30
        jb2.addActionListener(this);
31
        jp1.add(jb1);
32
        jp1.add(jb2);
33
       
34
        this.add(jp1);
35
        this.setSize(500, 400);
36
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
37
        this.setVisible(true);
38
    }
39
 
40
    @Override
41
    public void actionPerformed(ActionEvent e) {
42
        if(e.getSource()==jb1){
43
            new MyQqServer();
44
        }else if(e.getSource()==jb2){
45
            System.exit(0);
46
        }
47
    }
48
}

*******************************************************************************

com.qq.server.model

[MyQqServer.java]

55
 
1
/**
2
 * 这是QQ服务器,它在监听等待某个QQ客户端连接服务器
3
 */
4
package com.qq.server.model;
5
 
6
import java.io.BufferedReader;
7
import java.io.InputStreamReader;
8
import java.io.ObjectInputStream;
9
import java.io.ObjectOutputStream;
10
import java.net.ServerSocket;
11
import java.net.Socket;
12
import com.qq.common.Message;
13
import com.qq.common.User;
14
 
15
public class MyQqServer {
16
    BufferedReader br;
17
 
18
    public MyQqServer(){
19
        try {
20
            System.out.println("服务器在监听9999端口...");
21
            //在9999端口监听
22
            ServerSocket ss=new ServerSocket(9999);
23
            //等待连接
24
            while(true){
25
                Socket s=ss.accept();
26
                //接收客户端发来的信息
27
                ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
28
                User u=(User)ois.readObject();
29
                Message m=new Message();
30
                ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
31
                //此处代替数据库密码验证
32
                if(u.getPasswd().equals("12345")){
33
                    //返回一个成功登录的信息包
34
                    m.setMesType("1");
35
                    oos.writeObject(m);
36
                    //这里就单开一个线程,让该线程与该客户端保持通讯
37
                    SerConClientThread scct=new SerConClientThread(s);
38
                    ManageClientThrea.addClientThrea(u.getUserId(), scct);
39
                    //启动与该客户端通讯的线程
40
                    scct.start();
41
                   
42
                    //并通知其它在线用户
43
                    scct.notifyOther(u.getUserId());
44
                }else{
45
                    m.setMesType("2");
46
                    oos.writeObject(m);
47
                    //关闭连接
48
                    s.close();
49
                }
50
            }
51
        } catch (Exception e) {
52
            e.printStackTrace();
53
        }
54
    }
55
}

*******************************************************************************

[SerConClientThread.java]

75
 
1
/**
2
 * 功能:是服务器与某个客户端的通讯线程
3
 */
4
package com.qq.server.model;
5
 
6
import java.io.IOException;
7
import java.io.ObjectInputStream;
8
import java.io.ObjectOutputStream;
9
import java.net.Socket;
10
import java.util.HashMap;
11
import java.util.Iterator;
12
import com.qq.common.Message;
13
import com.qq.common.MessageType;
14
 
15
public class SerConClientThread extends Thread{
16
        Socket s;
17
   
18
    public SerConClientThread(Socket s){
19
        //把服务器与该客户端的连接赋给s
20
        this.s=s;
21
    }
22
   
23
    //让该线程去通知其它在线用户
24
    public void notifyOther(String iam){
25
        //得到所有在线的用户的线程
26
        HashMap hm=ManageClientThrea.hm;
27
        Iterator it=hm.keySet().iterator();
28
        while(it.hasNext()){
29
            Message m=new Message();
30
            m.setCon(iam);
31
            m.setMesType(MessageType.message_ret_onLineFriend);
32
            //取出在线用户的id
33
            String onLineUserId=it.next().toString();
34
            try {
35
                ObjectOutputStream oos=new ObjectOutputStream(ManageClientThrea.getClientThrea(onLineUserId).s.getOutputStream());
36
                m.setGetder(onLineUserId);
37
                oos.writeObject(m);
38
            } catch (IOException e) {
39
                e.printStackTrace();
40
            }
41
        }
42
    }
43
   
44
    public void run(){
45
        while(true){
46
            //这里该线程就可以接收客户端发来的信息
47
            try {
48
                ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
49
                Message m=(Message)ois.readObject();
50
               
51
                System.out.println(m.getSender()+" 给 "+m.getGetder()+" 说:"+m.getCon());
52
               
53
                //对从客户端取得的消息进行类型判断,然后做相应的处理
54
                if(m.getMesType().equals(MessageType.message_comm_mes)){
55
                    //服务器完成转发功能
56
                    //取得接收人的通讯线程
57
                    SerConClientThread sc=ManageClientThrea.getClientThrea(m.getGetder());
58
                    ObjectOutputStream oos=new ObjectOutputStream(sc.s.getOutputStream());
59
                    oos.writeObject(m);
60
                }else if(m.getMesType().equals(MessageType.message_get_onLineFriend)){
61
                    //把在服务器的好友给该客户端返回
62
                    String res=ManageClientThrea.getAllOnLineUserid();
63
                    Message m2=new Message();
64
                    m2.setMesType(MessageType.message_ret_onLineFriend);
65
                    m2.setCon(res);
66
                    m2.setGetder(m.getSender());
67
                    ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
68
                    oos.writeObject(m2);
69
                }
70
            } catch (Exception e) {
71
                e.printStackTrace();
72
            }
73
        }
74
    }
75
}

*******************************************************************************

[ManageClientThrea.java]

30
 
1
/**
2
 * 这是一个管理客户端线程的类
3
 */
4
package com.qq.server.model;
5
 
6
import java.util.HashMap;
7
import java.util.Iterator;
8
 
9
public class ManageClientThrea {
10
    public static HashMap hm=new HashMap<String,SerConClientThread>();
11
    //向hashmap中添加一个客户端通讯线程
12
    public static void addClientThrea(String uid,SerConClientThread scct){
13
        hm.put(uid,scct);
14
    }
15
   
16
    public static SerConClientThread getClientThrea(String uid){
17
        return (SerConClientThread)hm.get(uid);
18
    }
19
   
20
    //返回当前在线的人的好友情况
21
    public static String getAllOnLineUserid(){
22
        //使用迭代器完成
23
        Iterator it=hm.keySet().iterator();
24
        String res="";
25
        while(it.hasNext()){
26
            res+=it.next().toString()+" ";
27
        }
28
        return res;
29
    }
30
}

*******************************************************************************

com.qq.common

[Message.java]

57
 
1
/**
2
 * 为Message规定规则
3
 * mesType1-->表明登录成功
4
 * mesType2-->表明登录失败
5
 * mesType3-->表明普通消息包
6
 */
7
package com.qq.common;
8
 
9
import java.io.Serializable;
10
 
11
public class Message implements Serializable{
12
    private String mesType;
13
    private String sender;
14
    private String getder;
15
    private String con;
16
    private String sendTime;
17
 
18
    public String getGetder() {
19
        return getder;
20
    }
21
 
22
    public void setGetder(String getder) {
23
        this.getder = getder;
24
    }
25
 
26
    public String getSender() {
27
        return sender;
28
    }
29
 
30
    public void setSender(String sender) {
31
        this.sender = sender;
32
    }
33
 
34
    public String getCon() {
35
        return con;
36
    }
37
 
38
    public void setCon(String con) {
39
        this.con = con;
40
    }
41
 
42
    public String getSendTime() {
43
        return sendTime;
44
    }
45
 
46
    public void setSendTime(String sendTime) {
47
        this.sendTime = sendTime;
48
    }
49
 
50
    public String getMesType() {
51
        return mesType;
52
    }
53
 
54
    public void setMesType(String mesType) {
55
        this.mesType = mesType;
56
    }
57
}

*******************************************************************************

[MessageType.java]

12
 
1
/**
2
 * 定义消息包的种类的接口
3
 */
4
package com.qq.common;
5
 
6
public interface MessageType {
7
    String message_succeed="1";//登录成功包
8
    String message_login_fail="2";//登录失败包
9
    String message_comm_mes="3";//普通消息包
10
    String message_get_onLineFriend="4";//要求在线的好友包
11
    String message_ret_onLineFriend="5";//返回在线好友包
12
}

*******************************************************************************

[User.java]

25
 
1
/**
2
 * 这是用户信息类
3
 */
4
package com.qq.common;
5
 
6
import java.io.Serializable;
7
 
8
public class User implements Serializable{
9
    private String userId;
10
    private String passwd;
11
    public String getUserId() {
12
        return userId;
13
    }
14
    public void setUserId(String userId) {
15
        this.userId = userId;
16
    }
17
    public String getPasswd() {
18
        return passwd;
19
    }
20
    public void setPasswd(String passwd) {
21
        this.passwd = passwd;
22
    }
23
}
24
25





posted on 2018-12-01 00:35  XuCodeX  阅读(459)  评论(0编辑  收藏  举报

导航