相關閱讀: Java Socket聊天室編程(二)之利用socket實現單聊聊天室
網上已經有很多利用socket實現聊天的例子了,但是我看過很多,多多少有一些問題存在。
這裡我將實現一個比較完整的聊天例子,並解釋其中的邏輯。
由於socket這一塊比較大,所以我將分出幾篇來寫一個比較完整的socket例子。
這裡我們先來實現一個最簡單的,服務器與客戶端通訊,實現消息推送的功能。
目的:服務器與客戶端建立連接,客戶端可以向服務器發送消息,服務器可以向客戶端推送消息。
1,使用java建立socket聊天服務器
1,SocketUrls 確定ip地址和端口號
public class SocketUrls{// ip地址public final static String IP = "192.168.1.110";// 端口號public final static int PORT = 8888;}2,Main 程序的入口
public class Main {public static void main(String[] args) throws Exception {new ChatServer().initServer();}}3,Bean 實體類
用戶信息UserInfoBean
public class Main {public static void main(String[] args) throws Exception {new ChatServer().initServer();}}聊天信息MessageBean
public class MessageBean extends UserInfoBean {private long messageId;// 消息idprivate long groupId;// 群idprivate boolean isGoup;// 是否是群消息private int chatType;// 消息類型;1,文本;2,圖片;3,小視頻;4,文件;5,地理位置;6,語音;7,視頻通話private String content;// 文本消息內容private String errorMsg;// 錯誤信息private int errorCode;// 錯誤代碼//省略get/set方法}4,ChatServer 聊天服務,最主要的程序
public class ChatServer {// socket服務private static ServerSocket server;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 blocke.printStackTrace();}}/*** 創建消息管理,一直接收消息*/private void createMessage() {try {System.out.println("等待用戶接入: ");// 使用accept()阻塞等待客戶請求Socket socket = server.accept();System.out.println("用戶接入: " + socket.getPort());// 開啟一個子線程來等待另外的socket加入new Thread(new Runnable() {public void run() {createMessage();}}).start();// 向客戶端發送信息OutputStream output = socket.getOutputStream();// 從客戶端獲取信息BufferedReader bff = new BufferedReader(new InputStreamReader(socket.getInputStream()));// Scanner scanner = new Scanner(socket.getInputStream());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";output.write(buffer.getBytes("utf-8"));// 發送數據output.flush();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}).start();// 讀取發來服務器信息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);System.out.println("用戶: " + messageBean.getUserName());System.out.println("內容: " + messageBean.getContent());}}// server.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("錯誤: " + e.getMessage());}}}2,Android 端作為移動端連接服務器
1,appliaction 實例化一個全局的聊天服務
public class ChatAppliaction extends Application {public static ChatServer chatServer;public static UserInfoBean userInfoBean;@Overridepublic void onCreate() {super.onCreate();}}2,ip地址和端口號和服務器保持一致
3,聊天實力類同服務器端一樣
4,xml佈局。登陸,聊天
1,登錄
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/chat_name_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="用戶名"android:text="admin"/><EditTextandroid:id="@+id/chat_pwd_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="密碼"android:text="123123123a"android:inputType="numberPassword" /><Buttonandroid:id="@+id/chat_login_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="登錄" /></LinearLayout>
2,聊天
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".activity.MainActivity"><ScrollViewandroid:id="@+id/scrollView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="0.9"><LinearLayoutandroid:id="@+id/chat_ly"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"></LinearLayout></ScrollView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid:id="@+id/chat_et"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="0.8" /><Buttonandroid:id="@+id/send_btn"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="0.2"android:text="發送" /></LinearLayout></LinearLayout>
5,LoginActivity 登陸
public class LoginActivity extends AppCompatActivity {private EditText chat_name_text, chat_pwd_text;private Button chat_login_btn;@Overrideprotected 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() {@Overridepublic void onClick(View v) {if (getLogin(chat_name_text.getText().toString().trim(), chat_pwd_text.getText().toString().trim())) {getChatServer();Intent intent = new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);finish();}}});}private boolean getLogin(String name, String pwd) {if (TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)) return false;if (name.equals("admin") && pwd.equals("123123123a")) return true;return false;}private void getChatServer() {ChatAppliaction.chatServer = new ChatServer();}}6,MainActivity 聊天
public class MainActivity extends AppCompatActivity {private LinearLayout chat_ly;private TextView left_text, right_view;private EditText chat_et;private Button send_btn;private ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);chat_ly = (LinearLayout) findViewById(R.id.chat_ly);chat_et = (EditText) findViewById(R.id.chat_et);send_btn = (Button) findViewById(R.id.send_btn);send_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ChatAppliaction.chatServer.sendMessage(chat_et.getText().toString().trim());chat_ly.addView(initRightView(chat_et.getText().toString().trim()));}});//添加消息接收隊列ChatAppliaction.chatServer.setChatHandler(new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 1) {//發送回來消息後,更新uichat_ly.addView(initLeftView(msg.obj.toString()));}}});}/**靠右的消息* @param messageContent* @return*/private View initRightView(String messageContent) {right_view = new TextView(this);right_view.setLayoutParams(layoutParams);right_view.setGravity(View.FOCUS_RIGHT);right_view.setText(messageContent);return right_view;}/**靠左的消息* @param messageContent* @return*/private View initLeftView(String messageContent) {left_text = new TextView(this);left_text.setLayoutParams(layoutParams);left_text.setGravity(View.FOCUS_LEFT);left_text.setText(messageContent);return left_text;}}7,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() {initMessage();initChatServer();}/*** 消息隊列,用於傳遞消息** @param handler*/public void setChatHandler(Handler handler) {this.handler = handler;}private void initChatServer() {//開個線程接收消息receiveMessage();}/*** 初始化用戶信息*/private void initMessage() {messageBean = new MessageBean();messageBean.setUserId(1);messageBean.setMessageId(1);messageBean.setChatType(1);messageBean.setUserName("admin");ChatAppliaction.userInfoBean = messageBean;}/*** 發送消息** @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-8String 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() {@Overridepublic 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);Message message = handler.obtainMessage();message.obj = line;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();}}寫到這裡,已經完成了所有的代碼。
這個demo可以實現手機端向服務器發送消息,服務器向手機端發送消息。
這個demo可以算是推送功能,不過真正的推送沒有這麼簡單。作為一個socket的入門了解,可以從中看到socket編程的思想。
以上所述是小編給大家介紹的Java Socket聊天室編程(一)之利用socket實現聊天之消息推送,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!