原创 Android之Socket实例

2022-1-7 14:18 1805 21 21 分类: 软件与OS 文集: android studio

    Socket(套接字)是对 TCP/IP 协议的封装和应用,根据底层封装协议的不同,Socket 的类型可以分为流套接字(streamsocket)和数据报套接字(datagramsocket)两种。流套接字将TCP作为端对端协议,提供了一个可信赖的字节流服务;数据报套接字使用 UDP 协议,提供数据打包发送服务,应用程序可以通过它发送最长 64KB 的信息。Socket 的通信模型图如1-1所示。


图1-1 Socket 的通信模型图

通过图1-1可以很容易地看出,使用Socket进行两个应用程序之间的通信时可以选择使用TCP还是UDP作为其底层协议。对比两种方式,就会发现它们各有优劣,TCP 首先连接接收方,然后发送数据,保证成功率,速度相对较慢(相比 HTTP 方式还是非常快的);UDP 把数据打包成数据包,然后直接发送对应的IP 地址,速度快,但是不保证成功率,并且数据大小有限。

一个功能齐全的 Socket,都要包含以下基本结构,其工作过程包含4个基本的步骤∶创建Socket,打开连接到 Socket 的输入/出流,按照一定的协议对 Socket进行读/写操作,关闭 Socket。

Java在java.net包中提供了 Socket 和 ServerSocket 两个类,分别用来表示双向连接的客户端和服务端,是Socket编程的核心类。构造方法很多,一般情况下使用下面两种∶

Socket client = new Socket("127.0.0.1 ",999);

ServerSocket server = new ServerSocket(999);

其中,Socket 类用于实例化一个 Client,参数分别是要访问的IP 地址和端口号,这个端口号要与服务端一致。ServerSocket类用于实例化一个 Server,其中的参数用来设置端口这里的端口不能与"3306""80""8080"等常用端口号冲突。

下面以基于TCP的Socket为例来讲解如何使用Socket。

使用Java Socket创建一个服务端程序,运行在eclipse平台,并运行在PC上,然后在手机上编写客户端程序,在局域网内访问服务端。下面先编写服务端,代码如下:

  1. package socket;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.net.ServerSocket;
  8. import java.net.Socket;
  9. public class sockettest {
  10. public static void main(String[] args) throws IOException {
  11. @SuppressWarnings("resource")
  12. ServerSocket service = new ServerSocket(2226);
  13. while (true) {
  14. //等待客户端连接
  15. Socket socket = service.accept();
  16. new Thread(new AndroidRunable(socket)).start();
  17. }
  18. }
  19. }
  20. class AndroidRunable implements Runnable{
  21. Socket socket=null;
  22. public AndroidRunable(Socket socket)
  23. {
  24. this.socket=socket;
  25. }
  26. public void run(){
  27. //向Android客户端输出hello this is www.bigbirdic.com!
  28. String line=null;
  29. InputStream inputStream;
  30. OutputStream outputStream;
  31. String str="hello this is www.bigbirdic.com!";
  32. try{
  33. //向客户端发送信息
  34. outputStream=socket.getOutputStream();
  35. inputStream=socket.getInputStream();
  36. BufferedReader bfr=new BufferedReader(new InputStreamReader(inputStream));
  37. outputStream.write(str.getBytes("gbk"));
  38. outputStream.flush();
  39. //半关闭Socket
  40. socket.shutdownOutput();
  41. //获取客户端的信息
  42. while ((line=bfr.readLine())!=null){
  43. System.out.print(line);
  44. }
  45. //关闭输入输出流
  46. outputStream.close();
  47. bfr.close();
  48. inputStream.close();
  49. socket.close();
  50. }catch (IOException e)
  51. {
  52. e.printStackTrace();
  53. }
  54. }
  55. }

  这里的代码很简单,单纯地使用ServerSocket建立服务,设置端口号为2226,然后每当有客户端访问时就返回一个“hello this is www.bigbirdic.com!”。编辑完成服务端之后,我们在Android Studio中创建一个用于创建Socket客户端的类,代码如下:

  1. package com.rfstar.sockettest;
  2. import android.util.Log;
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.net.InetSocketAddress;
  8. import java.net.Socket;
  9. import java.net.SocketException;
  10. public class SocketUtil {
  11. private String str;
  12. private Socket socket;
  13. private String ip;
  14. public SocketUtil(String str,String ip){
  15. this.str=str;
  16. this.ip=ip;
  17. }
  18. public String sendMessage(){
  19. String result="";
  20. try{
  21. socket=new Socket();
  22. //ip为电脑所在的局域网网址
  23. socket.connect(new InetSocketAddress(ip,2226),5000);
  24. OutputStream outputStream=socket.getOutputStream();
  25. outputStream.write(str.getBytes());
  26. outputStream.flush();
  27. BufferedReader bfr=new BufferedReader(new InputStreamReader(socket.getInputStream()));
  28. String line=null;
  29. StringBuffer buffer=new StringBuffer();
  30. while ((line=bfr.readLine())!=null)
  31. {
  32. buffer.append(line);
  33. }
  34. result=buffer.toString();
  35. bfr.close();
  36. outputStream.close();
  37. socket.close();
  38. }catch (SocketException e)
  39. {
  40. //连接超时,在UI界面显示消息
  41. Log.i("socket",e.toString());
  42. }catch (IOException e)
  43. {
  44. e.printStackTrace();
  45. }
  46. return result;
  47. }
  48. }

  在本类中,使用Socket连接服务器端,然后发送相关信息并接收服务端数据。代码并不难,下面就在MainActivity中使用此类。当然,使用它之前要先修改MainActivity的布局文件activity_main.xml,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. tools:context=".MainActivity">
  9. <EditText
  10. android:id="@+id/message"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:paddingTop="50dp"
  14. android:textSize="24sp"/>
  15. <Button
  16. android:id="@+id/button"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:layout_marginTop="30dp"
  20. android:text="发送消息"
  21. android:textSize="20dp"/>
  22. <TextView
  23. android:id="@+id/content"
  24. android:layout_width="match_parent"
  25. android:layout_height="wrap_content"
  26. android:layout_marginTop="30dp"
  27. />
  28. </LinearLayout>

这里使用一个EditText来编辑向服务端发送的内容,并用一个Button来点击触发网络通信的事件,然后用一个TextView展示服务端返回的值。接下来在MainActivity中通过findViewById()方法来获取这些控件,并设置Button的点击事件,代码如下:

  1. package com.rfstar.sockettest;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Message;
  6. import android.view.View;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9. import android.widget.TextView;
  10. import org.w3c.dom.EntityReference;
  11. public class MainActivity extends AppCompatActivity {
  12. private Button button;
  13. private TextView textView;
  14. private String result;
  15. private Handler handler=new Handler(){
  16. @Override
  17. public void handleMessage(Message msg){
  18. super.handleMessage(msg);
  19. if(msg.what==123)
  20. {
  21. textView.setText(result);
  22. }
  23. }
  24. };
  25. @Override
  26. protected void onCreate(Bundle savedInstanceState) {
  27. super.onCreate(savedInstanceState);
  28. setContentView(R.layout.activity_main);
  29. initView();
  30. }
  31. private void initView()
  32. {
  33. textView=(TextView)findViewById(R.id.content);
  34. final EditText editText=(EditText)findViewById(R.id.message);
  35. button=(Button)findViewById(R.id.button);
  36. button.setOnClickListener(new View.OnClickListener() {
  37. @Override
  38. public void onClick(View v) {
  39. new Thread(new Runnable() {
  40. @Override
  41. public void run() {
  42. result=new SocketUtil(editText.getText().toString(),"192.168.110.82").sendMessage();
  43. handler.sendEmptyMessage(123);
  44. }
  45. }).start();
  46. }
  47. });
  48. }
  49. }

至此,实例代码完成,不要忘了还要在AndroidManifest.xml中申请权限:

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

  Activity中只是对点击事件做了处理,并将服务端返回的值展示在TextView上。添加完网络权限之后,运行程序,在EditText中输入内容,然后点击“发送消息”按钮,将“hello”发送到服务端,并接收到服务端返回的“hello this is www.bigbirdic.com!”,如图1-2所示。

观察服务端代码所在的控制台,发现也确实接收到了手机发送的内容,如图1-3所示。

1-2 Socket的通信:客户端发送并接收响应的消息

1-3 Socket通信:服务端接收到消息

android studio工具及手机模拟器以及更多工程源代码下载请前往微信公众号:大鸟科创空间,回复:android studio即可获取。

作者: 大鸟科创空间, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3949041.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
21
关闭 站长推荐上一条 /3 下一条