使用Socket進行一臺服務器與多個Android客戶端進行雙向通信

工具的準備:

編寫Web服務端的代碼:IDEA

編寫Android客戶端的代碼: Android Studio

web服務端的部署工具:Tomcat 7.0.82



代碼清單:

客戶端:

package com.example.administrator.filetransportapp;

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class MainActivity extends Activity {


    String IP="175.0.152.169";
    int PORT=8000;

    EditText et_message;
    TextView tv_result;
    StringBuffer stringBuffer=new StringBuffer();
    String message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Init();
    }

    public void Init(){

        et_message= (EditText) findViewById(R.id.message);
        tv_result= (TextView) findViewById(R.id.tv_result);

    }

    public void SendMessage(View v){
        Send();

    }

    public void Send(){
        Thread th=new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Socket socket=new Socket(IP,PORT);
                    if(socket.isConnected()){
                        System.out.println("連接主機成功");
                    }else{
                        System.out.println("連接主機失敗");
                    }
                    OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");

                         /* 客戶端向服務器發送數據  */
                    PrintWriter pw
                            = new PrintWriter(osw, true);
                    pw.println(et_message.getText().toString());

                         /* 客戶端接收服務器數據  */
                    InputStreamReader isr = new InputStreamReader(socket.getInputStream(), "UTF-8");
                    BufferedReader br = new BufferedReader(isr);
                    String msgReceive = null;

                    while(true) {
                        if((msgReceive = br.readLine()) != null) {
                            stringBuffer.append(msgReceive);
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tv_result.setText("\n"+stringBuffer.toString());
                                }
                            });
                            System.out.println("服務器說:" + msgReceive);
                        }
                    }

                } catch (IOException e) {
                    System.out.println("\nSocket的連接失敗");
                    e.printStackTrace();
                }
            }
        });

        th.start();



    }


}


服務端代碼清單【一共三個文件】:

1.ServerSocketThread類:

import java.io.*;
import java.net.Socket;

/**
 * <p>
 * Socket線程服務類
 * <p>
 *
 */
public class ServerSocketThread extends Thread {

    private Socket socket;

    public ServerSocketThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            // socket獲取字節輸入流
            is = socket.getInputStream();
            // 將字節輸入流轉字符輸入流
            isr = new InputStreamReader(socket.getInputStream(), "UTF-8");
            // 將字符輸入流轉行輸入流
            br = new BufferedReader(isr);
            String message = null;
           if ((message = br.readLine()) != null) {
                System.out.println("客戶端發來消息:" + message+socket.getRemoteSocketAddress());
            }
            // 必須先關閉輸入流才能獲取下面的輸出流
            socket.shutdownInput();
            String msgSend    = "\nhello I am server, I have receive your message: "+message;
            /* 服務器向客戶端發送數據  */
            OutputStreamWriter osw = null;
            osw = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
            pw = new PrintWriter(osw, true);
            pw.println(msgSend);
            pw.flush();
            System.out.println("向客戶端發送"+msgSend);


        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            // 關閉輸入流
            try {
                socket.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 收工前最後一步:關閉資源
            try {
                if (pw != null) {
                    pw.close();
                }
                if (br != null) {
                    br.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (os != null) {
                    os.close();
                }
                if (br != null) {
                    br.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }
}

2.Server類:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * <p>
 * 基於socket通訊-服務端
 */
public class Server {

    private static ServerSocket SERVER_SOCKET =null;;

    static{
        try {
            SERVER_SOCKET = new ServerSocket(8000);
        } catch (IOException e) {
            System.out.println("\n端口已被佔用");
            e.printStackTrace();
        }
    }
    public void start(){
     try {
            System.out.println("-----服務器已啓動,等待客戶端連接----");
            Socket socket = null;
             while(true){
                //循環監聽客戶端的連接
                socket = SERVER_SOCKET.accept();
                //新建一個線程ServerSocket,並開啓
                new ServerSocketThread(socket).start();
             }
         } catch (IOException e) {
            e.printStackTrace();
            }
}

    public static void main(String[] args) {
        try {
            System.out.println("-------服務器已啓動,等待客戶端連接----");
            Socket socket = null;
            while(true){
                //循環監聽客戶端的連接
                socket = SERVER_SOCKET.accept();
                //新建一個線程ServerSocket,並開啓
                new ServerSocketThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


3.ServerListener

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ServerListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                Server server=new Server();
                server.start();
            }
        });
        thread.start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}


最後就是運行效果了:

第一步:啓動服務端




第二步:打開Android虛擬機,發送消息



服務檯的打印臺輸出:



再用真機發送一句中文:


[虛擬機那邊,手抖,多按了一次發送,所以是發送了兩次good job]




好的,現在,代碼和效果已經展示完畢。

接下來記錄一下我在編寫代碼時遇見過的問題以及解決方法:

問題一:做內網測試時,我的服務器所在的臺式電腦與我的真機不在同一個內網,測試失敗,怎麼辦?

解決方法一:用虛擬機做測試,因爲電腦的虛擬機和臺式電腦肯定是在同一個內網。

解決方法二:用外網映射,具體操作看下圖:

第一步:查詢本機的IP,win+R,打開cmd,輸入:ipconfig查詢到我的本機IP是:192.168.1.102

第二步:設置外網映射,打開瀏覽器,在地址欄輸入:192.168.1.1 然後賬號密碼都是:admin

在網頁的左側,點擊轉發規則,在後面添加一個IP和Port:


第3步:查看電腦主機的外網IP地址

點擊網頁左側的運行狀態:


第四步:編寫代碼

服務端的Socket監聽端口,將端口改爲映射的端口,我的是8000.

在客戶端Socket連接的IP改爲服務器外網的IP,端口設置爲8000,與上面的保持一致。



問題二:如何給web服務器添加監聽?

這個問題,對各位讀者可能沒有普遍的借鑑意義,我就當是做個總結啦。

首先,要寫好Socket的Server,其次是編寫一個繼承了ServerletContextListener的類,並在web.xml進行註冊:


最重要的,差點忘記了,感謝以下兩位博主的分享,讓我可以學習,非常感謝~附上鍊接,有需要的讀者可以點擊進去查看

http://www.cnblogs.com/forget406/p/5336748.html

http://www.cnblogs.com/parryyang/p/6282563.html


發佈了40 篇原創文章 · 獲贊 32 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章