程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java Socket聊天室編程(二)之應用socket完成單聊聊天室

Java Socket聊天室編程(二)之應用socket完成單聊聊天室

編輯:關於JAVA

Java Socket聊天室編程(二)之應用socket完成單聊聊天室。本站提示廣大學習愛好者:(Java Socket聊天室編程(二)之應用socket完成單聊聊天室)文章只能為提供參考,不一定能成為您想要的結果。以下是Java Socket聊天室編程(二)之應用socket完成單聊聊天室正文


在上篇文章Java Socket聊天室編程(一)之應用socket完成聊天之新聞推送中我們講到若何應用socket讓辦事器和客戶端之間傳遞新聞,到達推送新聞的目標,接上去我將寫出若何讓辦事器樹立客戶端與客戶端之間的通信。

其實就是樹立一個一對一的聊天通信。

與上一篇完成新聞推送的代碼有些分歧,在它下面加以修正的。

假如沒有提到的辦法或許類則和上一篇如出一轍。

1,修正實體類(辦事器端和客戶真個實體類是一樣的)

1,UserInfoBean 用戶信息表

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 聊天信息表

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;// 文本新聞內容
private String errorMsg;// 毛病信息
private int errorCode;// 毛病代碼
private int userId;//用戶id
private int friendId;//目的石友id
private MessageFileBean chatFile;// 新聞附件
//省略get、set辦法
}

3,MessageFileBean 新聞附件表

public class MessageFileBean implements Serializable {
private static final long serialVersionUID = 3L;
private int fileId;//文件id
private String fileName;//文件稱號
private long fileLength;//文件長度
private Byte[] fileByte;//文件內容
private String fileType;//文件類型
private String fileTitle;//文件頭稱號
//省略get、set辦法
}

2,(辦事器端代碼修正)ChatServer 重要的聊天辦事類,加以修正

public class ChatServer {
// socket辦事
private static ServerSocket server;
// 應用ArrayList存儲一切的Socket
public List<Socket> socketList = new ArrayList<>();
// 模擬保留在內存中的socket
public Map<Integer, Socket> socketMap = new HashMap();
// 模擬保留在數據庫中的用戶信息
public Map<Integer, UserInfoBean> userMap = new HashMap();
public Gson gson = new Gson();
/**
* 初始化socket辦事
*/
public void initServer() {
try {
// 創立一個ServerSocket在端口8080監聽客戶要求
server = new ServerSocket(SocketUrls.PORT);
createMessage();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 創立新聞治理,一向吸收新聞
*/
private void createMessage() {
try {
System.out.println("期待用戶接入 : ");
// 應用accept()壅塞期待客戶要求
Socket socket = server.accept();
// 將鏈接出去的socket保留到聚集中
socketList.add(socket);
System.out.println("用戶接入 : " + socket.getPort());
// 開啟一個子線程來期待別的的socket參加
new Thread(new Runnable() {
public void run() {
// 再次創立一個socket辦事期待其他用戶接入
createMessage();
}
}).start();
// 用於辦事器推送新聞給用戶
getMessage();
// 從客戶端獲得信息
BufferedReader bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 讀取發來辦事器信息
String line = null;
// 輪回一向吸收以後socket發來的新聞
while (true) {
Thread.sleep(500);
// System.out.println("內容 : " + bff.readLine());
// 獲得客戶真個信息
while ((line = bff.readLine()) != null) {
// 解析實體類
MessageBean messageBean = gson.fromJson(line, MessageBean.class);
// 將用戶信息添加進入map中,模擬添加進數據庫和內存
// 實體類存入數據庫,socket存入內存中,都以用戶id作為參照
setChatMap(messageBean, socket);
// 將用戶發送出去的新聞轉發給目的石友
getFriend(messageBean);
System.out.println("用戶 : " + userMap.get(messageBean.getUserId()).getUserName());
System.out.println("內容 : " + messageBean.getContent());
}
}
// server.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("毛病 : " + e.getMessage());
}
}
/**
* 發送新聞
*/
private void getMessage() {
new Thread(new Runnable() {
public void run() {
try {
String buffer;
while (true) {
// 從掌握台輸出
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
buffer = strin.readLine();
// 由於readLine以換行符為停止點所以,開頭參加換行
buffer += "\n";
// 這裡修正成向全體銜接到辦事器的用戶推送新聞
for (Socket socket : socketMap.values()) {
OutputStream output = socket.getOutputStream();
output.write(buffer.getBytes("utf-8"));
// 發送數據
output.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
/**
* 模仿添加信息進入數據庫和內存
* 
* @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()));
}
// 將對應的鏈接出去的socket存起來
if (socketMap != null && socketMap.get(messageBean.getUserId()) == null) {
socketMap.put(messageBean.getUserId(), scoket);
}
}
/**
* 模仿數據庫的用戶信息,這裡創立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;
}
/**
* 將新聞轉發給目的石友
* 
* @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);
// 由於readLine以換行符為停止點所以,開頭參加換行
buffer += "\n";
try {
// 向客戶端發送信息
OutputStream output = socket.getOutputStream();
output.write(buffer.getBytes("utf-8"));
// 發送數據
output.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

3,(客戶端代碼)LoginActivity 上岸頁面修正可以登錄多人

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, "暗碼毛病", 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();
}
});
}
/**
* 前往上岸狀況,1為用戶,2為另外一個用戶,這裡模仿出兩個用戶相互通信
*
* @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;//暗碼毛病
}
}
/**
* 實例化一個聊天辦事
*
* @param status
*/
private void getChatServer(int status) {
ChatAppliaction.chatServer = new ChatServer(status);
}
}

4,(客戶端代碼)ChatServer 聊天辦事代碼邏輯的修正

public class ChatServer {
private Socket socket;
private Handler handler;
private MessageBean messageBean;
private Gson gson = new Gson();
// 由Socket對象獲得輸入流,並結構PrintWriter對象
PrintWriter printWriter;
InputStream input;
OutputStream output;
DataOutputStream dataOutputStream;
public ChatServer(int status) {
initMessage(status);
initChatServer();
}
/**
* 新聞隊列,用於傳遞新聞
*
* @param handler
*/
public void setChatHandler(Handler handler) {
this.handler = handler;
}
private void initChatServer() {
//開個線程吸收新聞
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");
//以下操作模擬當用戶點擊了某個石友睜開的聊天界面,將保留用戶id和聊天目的用戶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;
}
/**
* 發送新聞
*
* @param contentMsg
*/
public void sendMessage(String contentMsg) {
try {
if (socket == null) {
Message message = handler.obtainMessage();
message.what = 1;
message.obj = "辦事器曾經封閉";
handler.sendMessage(message);
return;
}
byte[] str = contentMsg.getBytes("utf-8");//將內容轉utf-8
String aaa = new String(str);
messageBean.setContent(aaa);
String messageJson = gson.toJson(messageBean);
/**
* 由於辦事器那裡的readLine()為壅塞讀取
* 假如它讀取不到換行符或許輸入流停止就會一向壅塞在那邊
* 所以在json新聞最初加上換行符,用於告知辦事器,新聞曾經發送終了了
* */
messageJson += "\n";
output.write(messageJson.getBytes("utf-8"));// 換行打印
output.flush(); // 刷新輸入流,使Server立時收到該字符串
} catch (Exception e) {
e.printStackTrace();
Log.e("test", "毛病:" + e.toString());
}
}
/**
* 吸收新聞,在子線程中
*/
private void receiveMessage() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 向本機的8080端口收回客戶要求
socket = new Socket(SocketUrls.IP, SocketUrls.PORT);
// 由Socket對象獲得輸出流,並結構響應的BufferedReader對象
printWriter = new PrintWriter(socket.getOutputStream());
input = socket.getInputStream();
output = socket.getOutputStream();
dataOutputStream = new DataOutputStream(socket.getOutputStream());
// 從客戶端獲得信息
BufferedReader bff = new BufferedReader(new InputStreamReader(input));
// 讀取發來辦事器信息
String line;
while (true) {
Thread.sleep(500);
// 獲得客戶真個信息
while ((line = bff.readLine()) != null) {
Log.i("socket", "內容 : " + 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();//封閉Socket輸入流
input.close();//封閉Socket輸出流
socket.close();//封閉Socket
} catch (Exception e) {
e.printStackTrace();
Log.e("test", "毛病:" + e.toString());
}
}
}).start();
}
public Socket getSocekt() {
if (socket == null) return null;
return socket;
}
}

如斯一來,代碼邏輯曾經從新聞推送的邏輯修正成了單聊的邏輯了。

這個代碼可讓用戶1和用戶2互相聊天,而且辦事器會記載下他們之間的聊天記載。而且辦事器照樣具有新聞推送的功效。

以上所述是小編給年夜家引見的Java Socket聊天室編程(二)之應用socket完成單聊聊天室,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved