JAVA入門到精通-網路程式設計補充和QQ案例
------------------------------------------------------
補充講解:
如何在網路間傳遞物件?
[MyServer.java]伺服器原始碼
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 1package 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 1package 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 1package 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.1、QqServerFrame.java (服務端主頁面)
2、com.qq.server.model (業務邏輯包)
2.1、MyQqServer.java (伺服器驗證客戶資訊)
2.2、QqServerUser.java (用於管理QQ使用者資訊[此包功能應為對資料庫邏輯操作])(空)
2.3、SerConClientThread.java (伺服器連線客戶端執行緒)
2.4、ManageClientThrea.java (管理客戶端連線執行緒)
3、com.qq.server.db (資料庫操作包)
3.1、SqlHelper.java (對資料庫的CURD操作)(空)
4、com.qq.server.tools (服務端工具包)(空)
5、com.qq.common (通用包)
5.1、Message.java (訊息類)
5.2、MessageType.java (訊息型別介面類)
5.3、User.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.1、QqClienConServer.java (客戶端連線服務端的後臺用於與服務端資料互動)
2.2、QqClientUser.java (客戶端使用者操作邏輯類)
3、com.qq.client.tools (原應為客戶端工具包,現為處理與服務端的執行緒包)
3.1、ClientConServerThread.java (客戶端連線伺服器執行緒類)
3.2、ManageClientConServerThread.java (管理C/S執行緒類)
3.3、ManageQqChat.java (管理聊天介面類)
3.4、ManageQqFriendList.java (管理好友列表類)
4、com.qq.common (通用包)
4.1、Message.java (訊息類)
4.2、MessageType.java(訊息型別類)
4.3、User.java (使用者資訊類)
注意:Server與Client中的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
}