深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信

1、功能介绍

(1)服务器端

发送消息、接收消息

(2)客户端

发送消息、接收消息

2、文件说明

(1)服务器端

深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信

TCP_Server.java 启动服务器相关操作的线程

ServerThread.java 执行线程内的操作(接收、发送消息)

(2)客户端

深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信

MainActivity.java 显示、更新客户端界面、启动客户端相关操作线程

ClientThread.java 执行线程内的操作(接收、发送消息)

3、代码说明

3、1、服务器端

(1) TCP_Server.java

public class TCP_Server {

    public static void main(String[] args) {
        int TCP_SERVER_PORT=12345;

        ServerThread serverThread = new ServerThread(TCP_SERVER_PORT);
        serverThread.start();

    }
}

(2)ServerThread.java

package com.example.chat_tcp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerThread extends Thread {
    //创建一个ServerSocket对象
    private ServerSocket serverSocket=null;

    //mTCP_SERVER_PORT为指定的绑定的端口,为int类型
    private int mTCP_SERVER_PORT;
    
    public ServerThread(int TCP_SERVER_PORT){
        this.mTCP_SERVER_PORT=TCP_SERVER_PORT;
    }
    @Override
    public void run(){
        super.run();

        try {
            serverSocket = new ServerSocket(mTCP_SERVER_PORT,100);
        }catch (IOException e){
            e.printStackTrace();
        }

            try{
                while (true) {
                    System.out.println("Server服务器正在监听");
                   

                    //监听连接请求
                    Socket socket = serverSocket.accept();
                    while (true) {
                        System.out.println("客户端已连接");
                        
                        //写入读Buffer中
                        BufferedReader in = new BufferedReader
                        (new InputStreamReader(socket.getInputStream())); //获取输入流
                        //放到写的Buffer中
                        BufferedWriter out = new BufferedWriter
                        (new OutputStreamWriter(socket.getOutputStream()));//获取输出流
                        
                        //读取接收信息,转换为字符串
                        String incomingMsg = in.readLine() + 
                        System.getProperty("line.separator");
                        //显示接收信息
                        System.out.println(incomingMsg);
                        
                        //生成发送字符串
                        BufferedReader br=new BufferedReader
                        (new InputStreamReader(System.in));
                        String outgoingMsg=null;
                        System.out.println("please enter you message:");
                        outgoingMsg=br.readLine();

                        outgoingMsg+=System.getProperty("line.separator") + "googbye 
                        from port:" + mTCP_SERVER_PORT + 
                        System.getProperty("line.separator");

                        //将发送字符串写入上面定义的BufferedWriter中
                        out.write(outgoingMsg);
                        //刷新,发送
                        out.flush();
                        
                        if(true) break;
                    }
                    //关闭socket
                    socket.close();
                }

            }catch (InterruptedIOException e){
                //超时错误
                e.printStackTrace();
            }catch (IOException e){
                //IO异常
                e.printStackTrace();
            }finally {
                //判定是否初始化ServerSocket对象,如果初始化则关闭serverSocket
                if(serverSocket!=null){
                    try {
                        serverSocket.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
    }
}

3、2、客户端

(1)MainAvtivity.java

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.net.Socket;

public class MainActivity extends AppCompatActivity {
    //服务器IP地址
    String localhost="192.168.155.4";
    //端口号
    final int PORT=12345;
    
    /相关布局
    EditText send_et;
    TextView receive_tv;
    TextView send_tv;
    Button send_btn;
    
    
    private void init_view()
    {
        send_et=findViewById(R.id.et_send_message);
        receive_tv=findViewById(R.id.tv_receive_mesage);
        send_tv=findViewById(R.id.tv_send_mesage);
        send_btn=findViewById(R.id.btn_send);

        send_tv.setMovementMethod(ScrollingMovementMethod.getInstance());
        receive_tv.setMovementMethod(ScrollingMovementMethod.getInstance());
    }
    
    //按钮点击响应事件
    public void btn_send_onClick(View view){
        ClientThread clientthread=new 
        ClientThread(localhost,PORT,mHandler,send_et.getText().toString());
        clientthread.start();
        Log.i("按钮点击事件响应:","客户端线程启动");

    }
    
    /*使用主线程的Handler*/
    //调用当前线程的Looper
    private Handler mHandler=new Handler(Looper.myLooper()){
        @Override
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            switch (msg.what){
                //用于更新发送消息界面的更新
                case 0x01:{
                    String content=(String)msg.obj;
                    System.out.println(content);
                    System.out.println("更新客户端发送内容");
                    send_tv.append(content);

                    break;
                }
                case 0x02:{
                    //用于更新接收消息界面的更新
                    String content=(String)msg.obj;
                    System.out.println(content);
                    System.out.println("更新客户端接收内容");
                    receive_tv.append(content);

                    break;
                }
            }

        }

    };


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

}

(2)ClientThread.java

package com.example.chat_tcp_client;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientThread extends Thread {

    private String LocalHost;
    private int TCP_SERVER_PORT;
    private Handler mhandler;
    private String msend_message;

    public ClientThread(String localhost, int port, Handler handler,String send_message)
    {
        this.LocalHost=localhost;
        this.TCP_SERVER_PORT=port;
        this.mhandler=handler;
        this.msend_message=send_message;

    }
  @Override
    public void run(){
        super.run();
        send_receive();

  }

    private void send_receive(){
        try {
            //初始化Socket,TCP_SERVER_PORT为指定的端口,int类型
            Socket socket=new Socket(LocalHost,TCP_SERVER_PORT);
            //获取输入流
            BufferedReader in=new BufferedReader(new 
            InputStreamReader(socket.getInputStream()));
            //生成输出流
            BufferedWriter out=new BufferedWriter((new 
            OutputStreamWriter(socket.getOutputStream())));

            //生成输出内容(to Server)
            String outMsg=System.getProperty("line.separator")+"TCP connecting to 
            "+TCP_SERVER_PORT+" "+msend_message+System.getProperty("line.separator");
            
            //写入
            out.write(outMsg);
            //刷新,发送
            out.flush();

            //使用Handler机制将客户端发送消息用于UI界面更新
            send_msg(0x01,outMsg);

            //生成输入内容(from Server)
            String inMsg=in.readLine()+System.getProperty("line.separator");
            Log.i("TCPClient","received:"+inMsg);

            //使用Handler机制将客户端接收消息用于UI界面更新
            receive_msg(0x02,inMsg);

            //关闭连接
            socket.close();

        }catch (UnknownHostException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private void send_msg(int what,String out_msg){
        Message msg=new Message();
        msg.what=what;
        msg.obj=out_msg;
        mhandler.sendMessage(msg);
    }

    private void receive_msg(int what,String in_msg){
        Message msg=new Message();
        msg.what=what;
        msg.obj=in_msg;
        mhandler.sendMessage(msg);

    }
}

(3)activity_main.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/border_write"
        android:hint="客户端接收的消息" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/tv_receive_mesage"
        android:scrollbars="vertical"
        android:fadeScrollbars="false"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/border_write"
        android:hint="客户端发送的消息" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/tv_send_mesage"
        android:scrollbars="vertical"
        android:fadeScrollbars="false"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="内容输入框"
        android:background="@drawable/border_write" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/et_send_message"
        android:hint="输入发送内容"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_send"
        android:onClick="btn_send_onClick"
        android:text="发送"/>

</LinearLayout>

(4)border_write.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!--实心-->
    <solid android:color="@android:color/white"/>
    <!--边框-->
    <stroke
        android:width="0.5dp"
        android:color="@android:color/white"/>
    <!--圆角-->
    <corners android:radius="3dp"/>
    <!--边距-->
    <padding
        android:bottom="5dp"
        android:top="5dp"
        android:left="5dp"
        android:right="5dp"/>
    <!--渐变-->
    <gradient
        android:angle="270"
        android:endColor="#FFFF"
        android:startColor="#13C7AF"/>

</shape>

4、运行结果

(1)服务器端

深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信

(2)客户端

深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信

深入理解Android网络编程——学习笔记(三)——使用TCP实现单客户端通信