android 通信之Socket

        基于android的Socket通信

一、Socket简介:

1.1 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者最大差异在于:

        Http: 使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。
        Socket: 在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。

1.2 通俗理解:Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。
                        Socket是应用层与传输层的一个抽象,将复杂的TCP/IP协议隐藏在Socket接口之后,只对用户暴露简单的接口。
1.3 表示方法:socket=(IP地址:端口号)
1.4 主要类型(根据底层不同的协议):a.流套接字(SOCK_STREAM)基于Tcp传输;b.数据报套接字(SOCK_DGRAM)基于udp传输;

   c.原始套接字(SOCK_RAW)原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。
       因此,如果要访问其他协议发送的数据必须使用原始套接
1.5 基本通信模型如下图:

 其中针对TCP socket通信通过,inputstream/outputstream进行流读取和写入。UDP经过datagram进行数据包的收发。

 二、Socket在android中的应用。

2.1 服务器端首先声明一个ServerSocket对象并且指定端口号,然后调用Serversocket的accept()方法接收客户端的数据。
accept()方法在没有数据进行接收的处于堵塞状态。(Socket socket=serversocket.accept()),一旦接收到数据,
通过inputstream读取接收的数据。
客户端创建一个Socket对象,指定服务器端的ip地址和端口号(Socket socket=newSocket("172.168.10.108",8080);),
通过inputstream读取数据,获取服务器发出的数据(OutputStream outputstream=socket.getOutputStream()),
最后将要发送的数据写入到outputstream即可进行TCP协议的socket数据传输。


2.2 通过如下demo 模拟socket在客户端的使用:

      2.2.1 在manifest进行权限声明,此处用的路由局域网。

<uses-permission android:name="android.permission.INTERNET" /> 

2.2.2 使用TCP通信,界面布局做一简单布置,不做过多介绍,界面只有有一button,来启动客户端和服务器两个线程,客户端写入的内容,将在服务端进行解析,后handler发送 在ui的TextView中显示。UI如下:
public class MainActivity<countClient> extends AppCompatActivity {
    TextView textView;
    EditText editText;
    Button bt;
    String tag = this.toString();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt = (Button) findViewById(R.id.bt);
        textView = (TextView) findViewById(R.id.textV);
        bt.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        new ServiceThread().start();//启动服务器
                        new ClientThread().start();//启动客户端
                    }
                }
        );
    }
public Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 100:
if(msg.obj == null) return;
Log.d(tag,"service receive..msg:" + msg.obj.toString());
textView.append(msg.obj.toString());
break;
}
}
};

   

2.2.3.客户端代码如下:

    public int countClient = 0;
    class ClientThread extends Thread {
        Socket mSocket = null;
        @Override
        public void run() {
            try {
                Log.d(tag,"ClientThread");
                mSocket = new Socket(/*"172.16.99.105"*/InetAddress.getLocalHost(), 9001);//链接服务器地址,端口9001.在使用此ip时可以先进行ping
                Log.d(tag,"InetAddress.getLocalHost:" + InetAddress.getLocalHost());
                OutputStream outputStream = mSocket.getOutputStream();
                PrintWriter pw = new PrintWriter(outputStream);
                countClient ++;
                pw.write("客户端给服务器端发送的数据"+countClient);
                pw.flush();
                //关闭输出流
                mSocket.shutdownOutput();
                pw.close();
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(tag,"Client IOExcept..e: " + e);
            }
        }
    }

2.2.4.服务端代码如下:

class ServiceThread extends Thread {
        ServerSocket mServiceSocket = null;
        Socket mSocket = null;
        TextView textView;
        @Override
        public void run() {
            try {
                Log.d(tag,"serviceThread");
                mServiceSocket = new ServerSocket(9001);//统一端口
                mSocket = mServiceSocket.accept();
                InputStream inputStream = mSocket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                StringBuilder sb = new StringBuilder();
                try {
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                        sb.append("\n");
                    }
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Message msg = new Message();
                msg.what =100;
                msg.obj = sb;
                mHandler.sendMessage(msg);
mSocket.close();
} catch (IOException e) { e.printStackTrace(); } } }

三、总结:

使用UDP方式通信和TCP发送接受大相径庭,相同都是进行ip端口设置,只是TCP使用的是流的方式发送,UDP是以包的形式发送。

完整demo可以下载:https://download.csdn.net/download/code_code_88/25312072

posted @ 2021-09-27 17:08  syyh2006  阅读(2326)  评论(0编辑  收藏  举报