激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室

Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室

2020-06-16 11:26夜輝疾風(fēng) JAVA教程

這篇文章主要介紹了Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

在上篇文章Java Socket聊天室編程(一)之利用socket實(shí)現(xiàn)聊天之消息推送中我們講到如何使用socket讓服務(wù)器和客戶端之間傳遞消息,達(dá)到推送消息的目的,接下來我將寫出如何讓服務(wù)器建立客戶端與客戶端之間的通訊。

其實(shí)就是建立一個(gè)一對(duì)一的聊天通訊。

與上一篇實(shí)現(xiàn)消息推送的代碼有些不同,在它上面加以修改的。

如果沒有提到的方法或者類則和上一篇一模一樣。

1,修改實(shí)體類(服務(wù)器端和客戶端的實(shí)體類是一樣的)

1,UserInfoBean 用戶信息表

?
1
2
3
4
5
6
7
8
9
public class UserInfoBean implements Serializable {
private static final long serialVersionUID = 2L;
private long userId;// 用戶id
private String userName;// 用戶名
private String likeName;// 昵稱
private String userPwd;// 用戶密碼
private String userIcon;// 用戶頭像
//省略get、set方法
}

2,MessageBean 聊天信息表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MessageBean implements Serializable {
private static final long serialVersionUID = 1L;
private long messageId;// 消息id
private long groupId;// 群id
private boolean isGoup;// 是否是群消息
private int chatType;// 消息類型;1,文本;2,圖片;3,小視頻;4,文件;5,地理位置;6,語音;7,視頻通話
private String content;// 文本消息內(nèi)容
private String errorMsg;// 錯(cuò)誤信息
private int errorCode;// 錯(cuò)誤代碼
private int userId;//用戶id
private int friendId;//目標(biāo)好友id
private MessageFileBean chatFile;// 消息附件
//省略get、set方法
}

3,MessageFileBean 消息附件表

?
1
2
3
4
5
6
7
8
9
10
public class MessageFileBean implements Serializable {
private static final long serialVersionUID = 3L;
private int fileId;//文件id
private String fileName;//文件名稱
private long fileLength;//文件長度
private Byte[] fileByte;//文件內(nèi)容
private String fileType;//文件類型
private String fileTitle;//文件頭名稱
//省略get、set方法
}

2,(服務(wù)器端代碼修改)ChatServer 主要的聊天服務(wù)類,加以修改

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
public class ChatServer {
// socket服務(wù)
private static ServerSocket server;
// 使用ArrayList存儲(chǔ)所有的Socket
public List<Socket> socketList = new ArrayList<>();
// 模仿保存在內(nèi)存中的socket
public Map<Integer, Socket> socketMap = new HashMap();
// 模仿保存在數(shù)據(jù)庫中的用戶信息
public Map<Integer, UserInfoBean> userMap = new HashMap();
public Gson gson = new Gson();
/**
* 初始化socket服務(wù)
*/
public void initServer() {
try {
// 創(chuàng)建一個(gè)ServerSocket在端口8080監(jiān)聽客戶請(qǐng)求
server = new ServerSocket(SocketUrls.PORT);
createMessage();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 創(chuàng)建消息管理,一直接收消息
*/
private void createMessage() {
try {
System.out.println("等待用戶接入 : ");
// 使用accept()阻塞等待客戶請(qǐng)求
Socket socket = server.accept();
// 將鏈接進(jìn)來的socket保存到集合中
socketList.add(socket);
System.out.println("用戶接入 : " + socket.getPort());
// 開啟一個(gè)子線程來等待另外的socket加入
new Thread(new Runnable() {
public void run() {
// 再次創(chuàng)建一個(gè)socket服務(wù)等待其他用戶接入
createMessage();
}
}).start();
// 用于服務(wù)器推送消息給用戶
getMessage();
// 從客戶端獲取信息
BufferedReader bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 讀取發(fā)來服務(wù)器信息
String line = null;
// 循環(huán)一直接收當(dāng)前socket發(fā)來的消息
while (true) {
Thread.sleep(500);
// System.out.println("內(nèi)容 : " + bff.readLine());
// 獲取客戶端的信息
while ((line = bff.readLine()) != null) {
// 解析實(shí)體類
MessageBean messageBean = gson.fromJson(line, MessageBean.class);
// 將用戶信息添加進(jìn)入map中,模仿添加進(jìn)數(shù)據(jù)庫和內(nèi)存
// 實(shí)體類存入數(shù)據(jù)庫,socket存入內(nèi)存中,都以用戶id作為參照
setChatMap(messageBean, socket);
// 將用戶發(fā)送進(jìn)來的消息轉(zhuǎn)發(fā)給目標(biāo)好友
getFriend(messageBean);
System.out.println("用戶 : " + userMap.get(messageBean.getUserId()).getUserName());
System.out.println("內(nèi)容 : " + messageBean.getContent());
}
}
// server.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("錯(cuò)誤 : " + e.getMessage());
}
}
/**
* 發(fā)送消息
*/
private void getMessage() {
new Thread(new Runnable() {
public void run() {
try {
String buffer;
while (true) {
// 從控制臺(tái)輸入
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
buffer = strin.readLine();
// 因?yàn)閞eadLine以換行符為結(jié)束點(diǎn)所以,結(jié)尾加入換行
buffer += "\n";
// 這里修改成向全部連接到服務(wù)器的用戶推送消息
for (Socket socket : socketMap.values()) {
OutputStream output = socket.getOutputStream();
output.write(buffer.getBytes("utf-8"));
// 發(fā)送數(shù)據(jù)
output.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
/**
* 模擬添加信息進(jìn)入數(shù)據(jù)庫和內(nèi)存
*
* @param messageBean
* @param scoket
*/
private void setChatMap(MessageBean messageBean, Socket scoket) {
// 將用戶信息存起來
if (userMap != null && userMap.get(messageBean.getUserId()) == null) {
userMap.put(messageBean.getUserId(), getUserInfoBean(messageBean.getUserId()));
}
// 將對(duì)應(yīng)的鏈接進(jìn)來的socket存起來
if (socketMap != null && socketMap.get(messageBean.getUserId()) == null) {
socketMap.put(messageBean.getUserId(), scoket);
}
}
/**
* 模擬數(shù)據(jù)庫的用戶信息,這里創(chuàng)建id不同的用戶信息
*
* @param userId
* @return
*/
private UserInfoBean getUserInfoBean(int userId) {
UserInfoBean userInfoBean = new UserInfoBean();
userInfoBean.setUserIcon("用戶頭像");
userInfoBean.setUserId(userId);
userInfoBean.setUserName("admin");
userInfoBean.setUserPwd("123123132a");
return userInfoBean;
}
/**
* 將消息轉(zhuǎn)發(fā)給目標(biāo)好友
*
* @param messageBean
*/
private void getFriend(MessageBean messageBean) {
if (socketMap != null && socketMap.get(messageBean.getFriendId()) != null) {
Socket socket = socketMap.get(messageBean.getFriendId());
String buffer = gson.toJson(messageBean);
// 因?yàn)閞eadLine以換行符為結(jié)束點(diǎn)所以,結(jié)尾加入換行
buffer += "\n";
try {
// 向客戶端發(fā)送信息
OutputStream output = socket.getOutputStream();
output.write(buffer.getBytes("utf-8"));
// 發(fā)送數(shù)據(jù)
output.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

3,(客戶端代碼)LoginActivity 登陸頁面修改可以登錄多人

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class LoginActivity extends AppCompatActivity {
private EditText chat_name_text, chat_pwd_text;
private Button chat_login_btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
chat_name_text = (EditText) findViewById(R.id.chat_name_text);
chat_pwd_text = (EditText) findViewById(R.id.chat_pwd_text);
chat_login_btn = (Button) findViewById(R.id.chat_login_btn);
chat_login_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int status = getLogin(chat_name_text.getText().toString().trim(), chat_pwd_text.getText().toString().trim());
if (status == -1 || status == 0) {
Toast.makeText(LoginActivity.this, "密碼錯(cuò)誤", Toast.LENGTH_LONG).show();
return;
}
getChatServer(getLogin(chat_name_text.getText().toString().trim(), chat_pwd_text.getText().toString().trim()));
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
});
}
/**
* 返回登陸狀態(tài),1為用戶,2為另一個(gè)用戶,這里模擬出兩個(gè)用戶互相通訊
*
* @param name
* @param pwd
* @return
*/
private int getLogin(String name, String pwd) {
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)) {
return 0;//沒有輸入完整密碼
} else if (name.equals("admin") && pwd.equals("1")) {
return 1;//用戶1
} else if (name.equals("admin") && pwd.equals("2")) {
return 2;//用戶2
} else {
return -1;//密碼錯(cuò)誤
}
}
/**
* 實(shí)例化一個(gè)聊天服務(wù)
*
* @param status
*/
private void getChatServer(int status) {
ChatAppliaction.chatServer = new ChatServer(status);
}
}

4,(客戶端代碼)ChatServer 聊天服務(wù)代碼邏輯的修改

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
public class ChatServer {
private Socket socket;
private Handler handler;
private MessageBean messageBean;
private Gson gson = new Gson();
// 由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象
PrintWriter printWriter;
InputStream input;
OutputStream output;
DataOutputStream dataOutputStream;
public ChatServer(int status) {
initMessage(status);
initChatServer();
}
/**
* 消息隊(duì)列,用于傳遞消息
*
* @param handler
*/
public void setChatHandler(Handler handler) {
this.handler = handler;
}
private void initChatServer() {
//開個(gè)線程接收消息
receiveMessage();
}
/**
* 初始化用戶信息
*/
private void initMessage(int status) {
messageBean = new MessageBean();
UserInfoBean userInfoBean = new UserInfoBean();
userInfoBean.setUserId(2);
messageBean.setMessageId(1);
messageBean.setChatType(1);
userInfoBean.setUserName("admin");
userInfoBean.setUserPwd("123123123a");
//以下操作模仿當(dāng)用戶點(diǎn)擊了某個(gè)好友展開的聊天界面,將保存用戶id和聊天目標(biāo)用戶id
if (status == 1) {//如果是用戶1,那么他就指向用戶2聊天
messageBean.setUserId(1);
messageBean.setFriendId(2);
} else if (status == 2) {//如果是用戶2,那么他就指向用戶1聊天
messageBean.setUserId(2);
messageBean.setFriendId(1);
}
ChatAppliaction.userInfoBean = userInfoBean;
}
/**
* 發(fā)送消息
*
* @param contentMsg
*/
public void sendMessage(String contentMsg) {
try {
if (socket == null) {
Message message = handler.obtainMessage();
message.what = 1;
message.obj = "服務(wù)器已經(jīng)關(guān)閉";
handler.sendMessage(message);
return;
}
byte[] str = contentMsg.getBytes("utf-8");//將內(nèi)容轉(zhuǎn)utf-8
String aaa = new String(str);
messageBean.setContent(aaa);
String messageJson = gson.toJson(messageBean);
/**
* 因?yàn)榉?wù)器那邊的readLine()為阻塞讀取
* 如果它讀取不到換行符或者輸出流結(jié)束就會(huì)一直阻塞在那里
* 所以在json消息最后加上換行符,用于告訴服務(wù)器,消息已經(jīng)發(fā)送完畢了
* */
messageJson += "\n";
output.write(messageJson.getBytes("utf-8"));// 換行打印
output.flush(); // 刷新輸出流,使Server馬上收到該字符串
} catch (Exception e) {
e.printStackTrace();
Log.e("test", "錯(cuò)誤:" + e.toString());
}
}
/**
* 接收消息,在子線程中
*/
private void receiveMessage() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 向本機(jī)的8080端口發(fā)出客戶請(qǐng)求
socket = new Socket(SocketUrls.IP, SocketUrls.PORT);
// 由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象
printWriter = new PrintWriter(socket.getOutputStream());
input = socket.getInputStream();
output = socket.getOutputStream();
dataOutputStream = new DataOutputStream(socket.getOutputStream());
// 從客戶端獲取信息
BufferedReader bff = new BufferedReader(new InputStreamReader(input));
// 讀取發(fā)來服務(wù)器信息
String line;
while (true) {
Thread.sleep(500);
// 獲取客戶端的信息
while ((line = bff.readLine()) != null) {
Log.i("socket", "內(nèi)容 : " + line);
MessageBean messageBean = gson.fromJson(line, MessageBean.class);
Message message = handler.obtainMessage();
message.obj = messageBean.getContent();
message.what = 1;
handler.sendMessage(message);
}
if (socket == null)
break;
}
output.close();//關(guān)閉Socket輸出流
input.close();//關(guān)閉Socket輸入流
socket.close();//關(guān)閉Socket
} catch (Exception e) {
e.printStackTrace();
Log.e("test", "錯(cuò)誤:" + e.toString());
}
}
}).start();
}
public Socket getSocekt() {
if (socket == null) return null;
return socket;
}
}

如此一來,代碼邏輯已經(jīng)從消息推送的邏輯修改成了單聊的邏輯了。

這個(gè)代碼可以讓用戶1和用戶2相互聊天,并且服務(wù)器會(huì)記錄下他們之間的聊天記錄。并且服務(wù)器還是擁有消息推送的功能。

以上所述是小編給大家介紹的Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!

原文鏈接:http://blog.csdn.net/yehui928186846/article/details/52583142

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 中文字幕爱爱视频 | 日本欧美一区二区三区在线播 | 成人视屏免费看 | 澳门一级淫片免费视频 | 黄色网址在线免费播放 | 亚洲婷婷日日综合婷婷噜噜噜 | 99视频有精品视频高清 | 看免费的毛片 | 欧美一区高清 | 成人区一区二区 | 日韩精品久久久久久久九岛 | 性生大片免费观看一片黄动漫 | 国产日产精品久久久久快鸭 | 久久69精品久久久久久国产越南 | 中文字幕在线观看日韩 | 黄在线看| 成人在线a| 免费国产不卡午夜福在线 | 精品国产九九九 | 黄wwww| 精品国产一区二区三区久久久蜜 | 成人福利网 | 亚洲第五色综合网 | 精品国产91一区二区三区 | 巨乳毛片 | 国产精品久久久久久久久久免 | 福利免费观看 | 在线成人免费观看视频 | 国产大片中文字幕在线观看 | 夫妻性生活交换 | 欧美毛片在线观看 | 成码无人av片在线观看网站 | 午夜色视频在线观看 | 亚洲欧美日韩久久精品第一区 | 久久艹艹艹 | 男女羞羞在线观看 | 亚洲一区二区三区精品在线观看 | 亚洲无av | 黄色片网站免费看 | 一边吃奶一边插下面 | 久久久电影电视剧免费看 |