欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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ù)器和客戶端之間傳遞消息,達(dá)到推送消息的目的,接下來我將寫出如何讓服務(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;//目標(biāo)好友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();
// 將鏈接進(jìn)來的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);
// 將用戶信息添加進(jìn)入map中,模仿添加進(jìn)數(shù)據(jù)庫和內(nèi)存
// 實體類存入數(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("錯誤 : " + 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();
}
/**
* 模擬添加信息進(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()));
}
// 將對應(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);
// 因為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和聊天目標(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);
/**
* 因為服務(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 {
// 向本機(jī)的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)文章

  • 關(guān)于MyBatis各種SQL操作詳解

    關(guān)于MyBatis各種SQL操作詳解

    這篇文章主要介紹了關(guān)于MyBatis各種SQL操作詳解,MyBatis 是一款優(yōu)秀的半自動的ORM持久層框架,它支持自定義 SQL、存儲過程以及高級映射,需要的朋友可以參考下
    2023-05-05
  • ThreadLocal原理及內(nèi)存泄漏原因

    ThreadLocal原理及內(nèi)存泄漏原因

    這篇文章主要介紹了ThreadLocal原理及內(nèi)存泄漏原因,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • 深入解析Java的Struts框架中的控制器DispatchAction

    深入解析Java的Struts框架中的控制器DispatchAction

    這篇文章主要介紹了深入解析Java的Struts框架中的控制器DispatchAction,Struts是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • SpringBoot RedisTemplate分布式鎖的項目實戰(zhàn)

    SpringBoot RedisTemplate分布式鎖的項目實戰(zhàn)

    本文主要介紹了SpringBoot RedisTemplate分布式鎖的項目實戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Java對象以Hash結(jié)構(gòu)存入Redis詳解

    Java對象以Hash結(jié)構(gòu)存入Redis詳解

    這篇文章主要介紹了Java對象以Hash結(jié)構(gòu)存入Redis詳解,和Java中的對象非常相似,卻不能按照J(rèn)ava對象的結(jié)構(gòu)直接存儲進(jìn)Redis的hash中,因為Java對象中的field是可以嵌套的,而Redis的Hash結(jié)構(gòu)不支持嵌套結(jié)構(gòu),需要的朋友可以參考下
    2023-08-08
  • 詳解Java線程池和Executor原理的分析

    詳解Java線程池和Executor原理的分析

    這篇文章主要介紹了詳解Java線程池和Executor原理的分析的相關(guān)資料,這里提供實例及分析原理幫助大家理解這部分知識,需要的朋友可以參考下
    2017-07-07
  • IDEA新建的Moudle失效顯示為灰色的完美解決方案

    IDEA新建的Moudle失效顯示為灰色的完美解決方案

    這篇文章主要介紹了IDEA新建的Moudle失效顯示為灰色,本文通過圖文并茂的形式給大家分享完美解決方案,需要的朋友可以參考下
    2023-09-09
  • Java微信支付之關(guān)閉訂單

    Java微信支付之關(guān)閉訂單

    這篇文章主要為大家詳細(xì)介紹了Java微信支付之關(guān)閉訂單,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 解決Spring Cloud Feign 請求時附帶請求頭的問題

    解決Spring Cloud Feign 請求時附帶請求頭的問題

    這篇文章主要介紹了解決Spring Cloud Feign 請求時附帶請求頭的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Java響應(yīng)式編程之handle用法解析

    Java響應(yīng)式編程之handle用法解析

    這篇文章主要介紹了Java響應(yīng)式編程之handle用法解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10

最新評論