使用Socket

Socket也稱為“套接字”,是網(wǎng)絡通信中的概念,它分為流式套接字和用戶數(shù)據(jù)報套接字兩種,分別對應于網(wǎng)絡的傳輸控制層的TCP和UDP協(xié)議。TCP協(xié)議是面向連接的協(xié)議,提供穩(wěn)定的雙向通信功能,TCP連接的建立需要經過“三次握手”才能生成,為了提供穩(wěn)定的數(shù)據(jù)傳輸功能,其本身提供了超時重傳機制,因此具有很高的穩(wěn)定性;而UDP是無連接的,提供不穩(wěn)定的單向通信功能,當然UDP也可以實現(xiàn)雙向通信功能。在性能上,UDP具有更好的效率,其缺點是不保證數(shù)據(jù)一定能夠正確傳輸,尤其是在網(wǎng)絡擁塞的情況下。

使用Socket來通信,有兩點需要注意,首先需要聲明權限:

圖一

其次要注意不能在主線程中訪問網(wǎng)絡,因為這會導致我們的程序無法在Android4.0及其以上的設備中運行,會拋出如下異常:android.os.NetworkOnMainThreadException。而且進行網(wǎng)絡操作很可能是耗時的,如果放在主線程中會影響程序的響應效率,從這方面來說,也不應該在主線程中訪問網(wǎng)絡。實際上通過Socket不僅僅能實現(xiàn)進程間通信,還可以實現(xiàn)設備間的通信,當然前提是這些設備之間的IP地址互相可見。

/*** 客戶端*/

public class TCPClientActivityextends Activityimplements View.OnClickListener {

private static final int MESSAGE_RECEIVE_NEW_MSG =1;

? ? private static final int MESSAGE_SOCKET_CONNECTED =2;

? ? private ButtonmSendButton;

? ? private TextViewmMessageTextView;

? ? private EditTextmMessageEditText;

? ? private PrintWritermPrintWriter;

? ? private SocketmClientSocket;

? ? private HandlermHandler =new Handler() {

@Override

? ? ? ? public void handleMessage(Message msg) {

// super.handleMessage(msg);

? ? ? ? ? ? switch (msg.what) {

case MESSAGE_RECEIVE_NEW_MSG: {

mMessageTextView.setText(mMessageTextView.getText() + (String) msg.obj);

break;

? ? ? ? ? ? ? ? }

case MESSAGE_SOCKET_CONNECTED: {

mSendButton.setEnabled(true);

break;

? ? ? ? ? ? ? ? }

default:

break;

? ? ? ? ? ? }

}

};

? ? @Override

? ? protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

? ? ? ? setContentView(R.layout.activtiy_tcpclient);

? ? ? ? mMessageTextView = findViewById(R.id.msg_container);

? ? ? ? mSendButton = findViewById(R.id.send);

? ? ? ? mSendButton.setOnClickListener(this);

? ? ? ? mMessageEditText = findViewById(R.id.msg);

? ? ? ? Intent service =new Intent(this, TCPServerService.class);

? ? ? ? startService(service);

? ? ? ? new Thread() {

@Override

? ? ? ? ? ? public void run() {

connectTCPServer();

? ? ? ? ? ? }

}.start();

? ? }

@Override

? ? protected void onDestroy() {

super.onDestroy();

? ? ? ? if (mClientSocket !=null) {

try {

mClientSocket.shutdownInput();

? ? ? ? ? ? ? ? mClientSocket.close();

? ? ? ? ? ? }catch (IOException e) {

e.printStackTrace();

? ? ? ? ? ? }

}

}

@Override

? ? public void onClick(View v) {

if (v ==mSendButton) {

final String msg =mMessageEditText.getText().toString();

? ? ? ? ? ? if (!TextUtils.isEmpty(msg) &&mPrintWriter !=null) {

new Thread(new Runnable() {

@Override

? ? ? ? ? ? ? ? ? ? public void run() {

mPrintWriter.println(msg);

? ? ? ? ? ? ? ? ? ? }

}).start();

? ? ? ? ? ? ? ? mMessageEditText.setText("");

? ? ? ? ? ? ? ? String time = formatDateTime(System.currentTimeMillis());

? ? ? ? ? ? ? ? final String showedMsg ="self" + time +":" + msg +"\n";

? ? ? ? ? ? ? ? mMessageTextView.setText(mMessageTextView.getText() + showedMsg);

? ? ? ? ? ? }

}

}

private StringformatDateTime(long time) {

return new SimpleDateFormat("(HH:MM:ss)").format(new Date(time));

? ? }

private void connectTCPServer() {

Socket socket =null;

? ? ? ? while (socket ==null) {

try {

socket =new Socket("localhost", 8688);

? ? ? ? ? ? ? ? mClientSocket = socket;

? ? ? ? ? ? ? ? mPrintWriter =new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

? ? ? ? ? ? ? ? mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);

? ? ? ? ? ? ? ? System.out.println("connect server success");

? ? ? ? ? ? }catch (IOException e) {

SystemClock.sleep(1000);

? ? ? ? ? ? ? ? System.out.println("connect tcp server failed,retry... ");

? ? ? ? ? ? }

}

try {

//接收服務器端的消息

? ? ? ? ? ? BufferedReader br =new BufferedReader(new InputStreamReader(socket.getInputStream()));

? ? ? ? ? ? while (!TCPClientActivity.this.isFinishing()) {

String msg = br.readLine();

? ? ? ? ? ? ? ? System.out.println("receive:" + msg);

? ? ? ? ? ? ? ? if (msg !=null) {

String time = formatDateTime(System.currentTimeMillis());

? ? ? ? ? ? ? ? ? ? final String showedMsg ="server " + time +":" + msg +"\n";

? ? ? ? ? ? ? ? ? ? mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showedMsg).sendToTarget();

? ? ? ? ? ? ? ? }

}

System.out.println("quit...");

? ? ? ? ? ? mPrintWriter.close();

? ? ? ? ? ? br.close();

? ? ? ? ? ? socket.close();

? ? ? ? }catch (IOException e) {

e.printStackTrace();

? ? ? ? }

}

}

/** * 服務端代碼 */

public class TCPServerServiceextends Service {

private boolean mIsServiceDestoryed =false;

? ? private String[]mDefinedMessages =new String[]{

"你好啊,哈哈",

? ? ? ? ? ? "請問你叫什么名字",

? ? ? ? ? ? "今天深圳天氣很好呀,shy",

? ? ? ? ? ? "你知道嗎?我可是可以和多個人聊天的哦",

? ? ? ? ? ? "給你講個笑話吧:據(jù)說愛笑的人運氣不會太差,不知道真假。"

? ? };

? ? @Override

? ? public void onCreate() {

new Thread(new TcpServer()).start();

? ? ? ? super.onCreate();

? ? }

@Nullable

@Override

? ? public IBinderonBind(Intent intent) {

return null;

? ? }

@Override

? ? public void onDestroy() {

mIsServiceDestoryed =true;

? ? ? ? super.onDestroy();

? ? }

private class TcpServerimplements Runnable {

@Override

? ? ? ? public void run() {

ServerSocket serverSocket =null;

? ? ? ? ? ? try {

serverSocket =new ServerSocket(8688);

? ? ? ? ? ? }catch (IOException e) {

System.err.println("establish tcp server failed,port:8688");

? ? ? ? ? ? ? ? e.printStackTrace();

return;

? ? ? ? ? ? }

while (!mIsServiceDestoryed) {

//接受客戶頓請求

? ? ? ? ? ? ? ? try {

final Socket client = serverSocket.accept();

? ? ? ? ? ? ? ? ? ? System.out.println("accept");

? ? ? ? ? ? ? ? ? ? new Thread() {

@Override

? ? ? ? ? ? ? ? ? ? ? ? public void run() {

try {

responseClient(client);

? ? ? ? ? ? ? ? ? ? ? ? ? ? }catch (IOException e) {

e.printStackTrace();

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

}

}.start();

? ? ? ? ? ? ? ? }catch (IOException e) {

e.printStackTrace();

? ? ? ? ? ? ? ? }

}

}

}

private void responseClient(Socket client)throws IOException {

//用于接受客戶端消息

? ? ? ? BufferedReader in =new BufferedReader(new InputStreamReader(client.getInputStream()));

? ? ? ? //用于向客戶端發(fā)送消息

? ? ? ? PrintWriter out =new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);

? ? ? ? out.println("歡迎來到聊天室!");

? ? ? ? while (!mIsServiceDestoryed) {

String str = in.readLine();

? ? ? ? ? ? System.out.println("msg from client:" + str);

? ? ? ? ? ? if (str ==null) {

//客戶端斷開連接

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

int i =new Random().nextInt(mDefinedMessages.length);

? ? ? ? ? ? String msg =mDefinedMessages[i];

? ? ? ? ? ? out.println(msg);

? ? ? ? ? ? System.out.println("send:" + msg);

? ? ? ? }

System.out.println("client quit.");

? ? ? ? //關閉流

? ? ? ? in.close();

? ? ? ? out.close();

? ? ? ? client.close();

? ? }

}


?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 多態(tài) 任何域的訪問操作都將有編譯器解析,如果某個方法是靜態(tài)的,它的行為就不具有多態(tài)性 java默認對象的銷毀順序與...
    yueyue_projects閱讀 1,095評論 0 1
  • 前言 兩個進程如果要進行通訊最基本的一個前提就是能夠唯一的標識一個進程,在本地進程通訊中我們可以使用 PID...
    米奇小林閱讀 3,842評論 3 19
  • 昨天是你的演唱會,很成功。 昨天是喜歡你這么多年來,第一次去聽你的演唱會,也是我第一次聽演唱會,很震撼很high,...
    木魚槌子閱讀 310評論 0 1
  • 我們經常在任何事情上都會競爭,會遇到各種困難,我們通常會遇到一些我們無法攻克的難題,而花費大筆大筆的時間和金錢,通...
    指針指向你心臟閱讀 571評論 0 0
  • “昨晚和林醫(yī)生聊得愉快嗎?”蘇蘇推門進來,把水果零食放到柜子里。她坐在床邊,用手整理著花瓶里的百合,將它們調...
    棖不戒閱讀 295評論 0 1

友情鏈接更多精彩內容