最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2016年09月19日 11:28:20   作者:夜輝疾風(fēng)  
這篇文章主要介紹了Java Socket聊天室編程(二)之利用socket實現(xiàn)單聊聊天室的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

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

其實就是建立一個一對一的聊天通訊。

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

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

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

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;// 文本消息內(nèi)容
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;//文件內(nèi)容
private String fileType;//文件類型
private String fileTitle;//文件頭名稱
//省略get、set方法
}

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

public class ChatServer {
// socket服務(wù)
private static ServerSocket server;
// 使用ArrayList存儲所有的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)建一個ServerSocket在端口8080監(jiān)聽客戶請求
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()阻塞等待客戶請求
Socket socket = server.accept();
// 將鏈接進來的socket保存到集合中
socketList.add(socket);
System.out.println("用戶接入 : " + socket.getPort());
// 開啟一個子線程來等待另外的socket加入
new Thread(new Runnable() {
public void run() {
// 再次創(chuàng)建一個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) {
// 解析實體類
MessageBean messageBean = gson.fromJson(line, MessageBean.class);
// 將用戶信息添加進入map中,模仿添加進數(shù)據(jù)庫和內(nèi)存
// 實體類存入數(shù)據(jù)庫,socket存入內(nèi)存中,都以用戶id作為參照
setChatMap(messageBean, socket);
// 將用戶發(fā)送進來的消息轉(zhuǎn)發(fā)給目標好友
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("錯誤 : " + e.getMessage());
}
}
/**
* 發(fā)送消息
*/
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以換行符為結(jié)束點所以,結(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();
}
/**
* 模擬添加信息進入數(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()));
}
// 將對應(yīng)的鏈接進來的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ā)給目標好友
* 
* @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以換行符為結(jié)束點所以,結(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 登陸頁面修改可以登錄多人

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();
}
});
}
/**
* 返回登陸狀態(tài),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;//密碼錯誤
}
}
/**
* 實例化一個聊天服務(wù)
*
* @param status
*/
private void getChatServer(int status) {
ChatAppliaction.chatServer = new ChatServer(status);
}
}

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

public class ChatServer {
private Socket socket;
private Handler handler;
private MessageBean messageBean;
private Gson gson = new Gson();
// 由Socket對象得到輸出流,并構(gòu)造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");
//以下操作模仿當(dāng)用戶點擊了某個好友展開的聊天界面,將保存用戶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;
}
/**
* 發(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);
/**
* 因為服務(wù)器那邊的readLine()為阻塞讀取
* 如果它讀取不到換行符或者輸出流結(jié)束就會一直阻塞在那里
* 所以在json消息最后加上換行符,用于告訴服務(wù)器,消息已經(jīng)發(fā)送完畢了
* */
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端口發(fā)出客戶請求
socket = new Socket(SocketUrls.IP, SocketUrls.PORT);
// 由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象
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", "錯誤:" + e.toString());
}
}
}).start();
}
public Socket getSocekt() {
if (socket == null) return null;
return socket;
}
}

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

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

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

相關(guān)文章

  • java集合map取key使用示例 java遍歷map

    java集合map取key使用示例 java遍歷map

    這篇文章主要介紹了java集合map取key使用示例,需要的朋友可以參考下
    2014-02-02
  • 談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題

    談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題

    中文亂碼是每個程序員都會遇到的問題,本篇文章主要介紹了談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12
  • 深度解析Spring內(nèi)置作用域及其在實踐中的應(yīng)用

    深度解析Spring內(nèi)置作用域及其在實踐中的應(yīng)用

    這篇文章主要詳細介紹了Spring內(nèi)置的作用域類型及其在實踐中的應(yīng)用,文中有詳細的代碼示例,對我們的餓學(xué)習(xí)或工作有一定的參考價值,感興趣的同學(xué)可以借鑒閱讀
    2023-06-06
  • 微信支付java版本之Native付款

    微信支付java版本之Native付款

    這篇文章主要為大家詳細介紹了微信支付java版本之Native付款,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Java中Cglib代理類重寫邏輯詳解

    Java中Cglib代理類重寫邏輯詳解

    這篇文章主要介紹了Java中Cglib代理類重寫邏輯詳解,代理類中只會維護NoOp這個回調(diào)屬性,并不會生成目標類MyService中的noOp所對應(yīng)的方法,需要的朋友可以參考下
    2023-11-11
  • Java?Optional避免空指針異常的實現(xiàn)

    Java?Optional避免空指針異常的實現(xiàn)

    空指針異常一直是困擾開發(fā)者的常見問題之一,本文主要介紹了Java?Optional避免空指針異常的實現(xiàn),幫助開發(fā)者編寫更健壯、可讀性更高的代碼,減少因空值處理不當(dāng)而引發(fā)的錯誤,感興趣的可以了解一下
    2025-04-04
  • SpringBoot整合mybatis通用Mapper+自定義通用Mapper方法解析

    SpringBoot整合mybatis通用Mapper+自定義通用Mapper方法解析

    這篇文章主要介紹了SpringBoot整合mybatis通用Mapper+自定義通用Mapper方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java子類調(diào)用父類的私有屬性的實現(xiàn)示例

    Java子類調(diào)用父類的私有屬性的實現(xiàn)示例

    在Java中,我們都知道子類不能直接訪問或修改父類的私有屬性,本文主要介紹了Java子類調(diào)用父類的私有屬性的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Java實現(xiàn)去重的方法詳解

    Java實現(xiàn)去重的方法詳解

    austin支持兩種去重的類型:N分鐘相同內(nèi)容達到N次去重和一天內(nèi)N次相同渠道頻次去重,這篇文章就來和大家講講這兩種去重的具體實現(xiàn),需要的可以參考一下
    2023-06-06
  • Java刪除ArrayList中的重復(fù)元素的兩種方法

    Java刪除ArrayList中的重復(fù)元素的兩種方法

    在Java編程中,ArrayList是一種常用的集合類,它允許我們存儲一組元素,在某些情況下,我們可能需要移除其中重復(fù)的元素,只保留唯一的元素,下面介紹兩種常見的刪除ArrayList中重復(fù)元素的方法,需要的朋友可以參考下
    2024-12-12

最新評論

麦盖提县| 苍南县| 玛沁县| 息烽县| 垦利县| 奇台县| 桑植县| 凤翔县| 永福县| 汉源县| 盐池县| 阳山县| 和田县| 丰都县| 吉林省| 绍兴市| 颍上县| 东明县| 元江| 水城县| 龙川县| 阿鲁科尔沁旗| 兰坪| 宾阳县| 沧源| 台中县| 长治县| 万盛区| 城固县| 车致| 高青县| 巴彦县| 嘉定区| 讷河市| 台北市| 安溪县| 临朐县| 武穴市| 赞皇县| 利辛县| 高密市|