美文网首页
Android Socket 的使用方法

Android Socket 的使用方法

作者: 付凯强 | 来源:发表于2022-04-30 19:16 被阅读0次

    引言

    Socket是位于应用层和传输层之间的一个抽象层,把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用以实现进程在网络中通信。
    Socket分为流式套接字和数据包套接字,分别对应网络传输控制层的TCP协议和UDP协议。TCP协议是一种面向连接的,可靠的,基于字节流的传输层通信协议,它使用三次握手协议建立连接,并且提供了超时重传机制,具有很高的稳定性。UDP协议是一种无连接的协议,且不对数据包进行可靠性保证。
    在网络差的情况下,UDP协议数据包丢失会比较严重,但由于其不属于连接型协议,具有资源消耗少,处理速度快的优点,在音频视频等传输时使用UDP协议较多。

    示例

    这里我们通过socket实现两个进程之间的通信。

    1. 建立两个工程,分别是TestServerSocket和TestClientSocket,并分别增加权限。
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
    1. TestServerSocket
      当server service启动的时候,创建ServerSocket,对端口8688进行监听;然后进行while循环,在循环中阻塞线程直到接收到客户端消息;收到客户端消息的时候会收到客户端的Socket,然后开启while循环,通过InputStream获取其消息,通过OutputStream向其发送消息。
    • MainActivity
        @Override
        protected void onResume() {
            super.onResume();
            startService(new Intent(this,SocketServerService.class));
        }
    
    • SocketServerService
    public class SocketServerService extends Service {
        private boolean isServiceDestroyed = false;
        private static final String TAG = "SocketServerService";
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        @Override
        public void onCreate() {
            super.onCreate();
            new Thread(new TcpServer()).start();
        }
        private class TcpServer implements Runnable{
            @Override
            public void run() {
                ServerSocket serverSocket = null;
                try{
                    serverSocket = new ServerSocket(8688);
                }catch (IOException exception){
                    exception.printStackTrace();
                }
                while(!isServiceDestroyed){
                    try {
                        if (serverSocket == null){
                            return;
                        }
                        Log.i(TAG, "ServerSocket loop listen ClientSocket");
                        //接收客户端的请求,并且阻塞直到接收到消息
                        final Socket client = serverSocket.accept();
                        new Thread(() -> {
                            try {
                                responseClient(client);
                            } catch (IOException exception) {
                                exception.printStackTrace();
                            }
                        }).start();
                    }catch (IOException exception){
                        exception.printStackTrace();
                    }
                }
    
            }
        }
        private void responseClient(Socket client) throws IOException{
            // 用于接收客户端的消息
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            // 用于向客户端发送消息
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    client.getOutputStream())),true);
            out.println("你好,我是服务端");
            while(!isServiceDestroyed){
                String str = in.readLine();
                Log.i(TAG, "收到客户端发来的消息" + str);
                if (TextUtils.isEmpty(str)){
                    //客户端断开了连接
                    Log.i(TAG, "客户端断开了连接");
                    break;
                }
                String message = "收到了客户端的消息为:" + str;
                // 从客户端收到的消息加工再发送给客户端
                out.println(message);
            }
            out.close();
            in.close();
            client.close();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            isServiceDestroyed = true;
        }
    }
    

    3.TestClientSocket
    客户端首先就是开启while循环,创建Socket与ServerSocket进行连接,直到建立与ServerSocket的连接;然后同样是获得ServerSocket,通过InputStream读取其内容,通过OutputStream向其写入内容。

    public class MainActivity extends AppCompatActivity {
    
        private PrintWriter mPrintWriter;
        private EditText mEt_receive;
        private TextView mTv_message;
        private static final String TAG = "TestClientService";
        private Handler mHandler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message message) {
                mTv_message.setText(String.format("%s\n客户端:%s", mTv_message.getText(), message.obj));
                mEt_receive.setText("");
                return true;
            }
        });
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            new Thread(this::connectSocketServer).start();
        }
    
        private void initView() {
            mEt_receive = findViewById(R.id.et_receive);
            Button mBt_send = findViewById(R.id.bt_send);
            mTv_message = findViewById(R.id.tv_message);
            mBt_send.setOnClickListener(view -> {
                final String msg = mEt_receive.getText().toString();
                //向服务器发送消息
                if (!TextUtils.isEmpty(msg) && null!=mPrintWriter){
                    new Thread(() -> {
                        mPrintWriter.println(msg);
                        Message message = Message.obtain();
                        message.what = 0;
                        message.obj = msg;
                        mHandler.sendMessage(message);
                    }).start();
                }
            });
        }
    
        private void connectSocketServer() {
            Socket socket = null;
            while (socket == null){
                try {
                    //选择和服务器相同的ip和端口 8688
                    socket = new Socket("192.168.1.3",8688);
                    mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                            socket.getOutputStream())),true);
                }catch (IOException exception){
                    Log.d(TAG, "connectSocketServer: " + exception);
                    SystemClock.sleep(1000);
                }
            }
            try {
                // 用于接收服务端的消息
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while(!isFinishing()){
                    final String msg = br.readLine();
                    if (msg != null){
                        runOnUiThread(() ->
                                mTv_message.setText(
                                String.format("%s\n服务端:%s", mTv_message.getText(), msg)));
                    }
                }
                mPrintWriter.close();
                br.close();
                socket.close();
            }catch (IOException exception){
                exception.printStackTrace();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
    }
    
    1. 先打开服务端
    2022-04-30 ... com.example.testserversocket I/SocketServerService: ServerSocket loop listen ClientSocket
    

    4.再打开客户端
    客户端开启之后建立与服务端的连接。


    客户端建立了与服务端的连接.jpg

    连接创建好之后,客户端向服务端发送信息。


    服务端收到了客户端发送的信息.jpg
    2022-04-30 ... com.example.testserversocket I/SocketServerService: 收到客户端发来的消息你好,我是客户端
    

    总结

    在上层,socket基于对相同IP和相同端口的监听实现的。

    参考

    刘望舒的Android进阶指北。

    相关文章

      网友评论

          本文标题:Android Socket 的使用方法

          本文链接:https://www.haomeiwen.com/subject/qwsqhftx.html