Android中socket通信的简单实现

作者:feng海涛 时间:2023-01-21 12:24:22 

Android中socket通信简单实现,供大家参考,具体内容如下

socket通信需要有一个服务器和客户端,可以把同一个APP作为服务器跟客户端,也可以分开成两个APP。
先上个图:

Android中socket通信的简单实现

这里以一个APP作为服务器跟客户端为示例

1、添加网络访问权限


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

2、写服务器,在APP上启动


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

ServerSocket serverSocket = null;
public final int port = 9998;
private int i = 0;

public Server(){

//输出服务器的IP地址
 try {
  InetAddress addr = InetAddress.getLocalHost();
  System.out.println("local host:"+addr);
  serverSocket = new ServerSocket(port);
  System.out.println("0k");
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
}

public void startService(){

try {
  Socket socket = null;
  System.out.println("waiting...");
  //等待连接,每建立一个连接,就新建一个线程
  while(true){
   socket = serverSocket.accept();//等待一个客户端的连接,在连接之前,此方法是阻塞的
   System.out.println("connect to"+socket.getInetAddress()+":"+socket.getLocalPort());
   new ConnectThread(socket).start();
  }

} catch (IOException e) {
  // TODO Auto-generated catch block
  System.out.println("IOException");
  e.printStackTrace();
 }
}

//向客户端发送信息
class ConnectThread extends Thread{
 Socket socket = null;

public ConnectThread(Socket socket){
  super();
  this.socket = socket;
 }

@Override
 public void run(){
  try {
   DataInputStream dis = new DataInputStream(socket.getInputStream());
   DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
   while(true){
    i++;
    String msgRecv = dis.readUTF();
    System.out.println("msg from client:"+msgRecv);
    dos.writeUTF(msgRecv + i);
    dos.flush();
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}
}

需要在线程中调用,调用方法:


new Thread(() -> new Server().startService()).start();

3、客户端代码


import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import androidx.appcompat.app.AppCompatActivity;

/**
* @author fenghaitao
* @time 2020年4月2日14:34:33
* scoket客户端连接测试
*/
public class SocketActivity extends AppCompatActivity {
//IP地址和端口号
public static String IP_ADDRESS = "";
public static int PORT = 9998;
//三个控件
EditText et_message = null; //需要发送的内容
Button bt_getAdress = null; //获取本机IP地址
Button bt_connect = null; //连接并发送
Button bt_startServer = null; //启动服务端
TextView tv_adress = null; //ip地址
TextView tv_reply = null; //服务器回复的消息
//handler
Handler handler = null;
Socket soc = null;
DataOutputStream dos = null;
DataInputStream dis = null;
String messageRecv = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_socket);
 et_message = findViewById(R.id.et_message);
 bt_getAdress = findViewById(R.id.bt_getAdress);
 bt_connect = findViewById(R.id.bt_connect);
 bt_startServer = findViewById(R.id.bt_startServer);

tv_adress = findViewById(R.id.tv_adress);
 tv_reply = findViewById(R.id.tv_reply);
 bt_getAdress.setOnClickListener(v -> {
  new Thread(() -> {
   try {
    InetAddress addr = InetAddress.getLocalHost();
    System.out.println("local host:"+addr);
    runOnUiThread(() -> tv_adress.setText(addr.toString().split("/")[1]));
   } catch (UnknownHostException e) {
    e.printStackTrace();
   }
  }).start();
 });

bt_startServer.setOnClickListener(v -> {
  new Thread(() -> new Server().startService()).start();
  Toast.makeText(SocketActivity.this,"服务已启动",Toast.LENGTH_SHORT).show();
 });
 bt_connect.setOnClickListener(v -> {
  IP_ADDRESS = tv_adress.getText().toString();
  new ConnectionThread(et_message.getText().toString()).start();
 });
 handler = new Handler(msg -> {
  Bundle b = msg.getData(); //获取消息中的Bundle对象
  String str = b.getString("data"); //获取键为data的字符串的值
  tv_reply.append(str);
  return false;
 });
}

//新建一个子线程,实现socket通信
class ConnectionThread extends Thread {
 String message = null;

public ConnectionThread(String msg) {
  message = msg;
 }

@Override
 public void run() {
  if (soc == null) {
   try {
    //Log.d("socket","new socket");
    if ("".equals(IP_ADDRESS)) {
     return;
    }
    soc = new Socket(IP_ADDRESS, PORT);
    //获取socket的输入输出流
    dis = new DataInputStream(soc.getInputStream());
    dos = new DataOutputStream(soc.getOutputStream());
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  try {
   dos.writeUTF(message);
   dos.flush();
   messageRecv = dis.readUTF();//如果没有收到数据,会阻塞
   Message msg = new Message();
   Bundle b = new Bundle();
   b.putString("data", messageRecv);
   msg.setData(b);
   handler.sendMessage(msg);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}
}

下面是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"
tools:context=".SocketActivity">
<LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="10dp">
  <Button
   android:id="@+id/bt_getAdress"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="获取IP地址"/>

<TextView
   android:id="@+id/tv_adress"
   android:layout_width="200dp"
   android:layout_height="match_parent"
   android:layout_marginLeft="15dp"
   android:textSize="20dp"
   android:gravity="center"/>
 </LinearLayout>
 <Button
  android:id="@+id/bt_startServer"
  android:text="启动服务"
  android:layout_marginTop="10dp"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
 <EditText
  android:id="@+id/et_message"
  android:layout_marginTop="10dp"
  android:hint="请输入发送信息"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
 <Button
  android:id="@+id/bt_connect"
  android:text="连接发送"
  android:layout_marginTop="10dp"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>

<TextView
  android:id="@+id/tv_reply"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginTop="10dp"
  android:text="服务端返回消息:"
  android:textSize="30sp"/>
</LinearLayout>
</LinearLayout>

客户端跟服务器进行通信之前记得先启动服务器,如果端口被占用需要换个端口。

来源:https://blog.csdn.net/weixin_42574892/article/details/105270472

标签:Android,socket,通信
0
投稿

猜你喜欢

  • Java多线程之多种锁和阻塞队列

    2023-09-26 10:31:55
  • 基于javaWeb 项目SSM配置要点及可能遇到的问题和解决方法

    2023-10-27 21:45:16
  • SpringBoot 2.x整合Log4j2日志的详细步骤

    2022-08-05 09:50:19
  • 浅谈java中静态方法的重写问题详解

    2022-12-24 10:13:04
  • Java 泛型总结(一):基本用法与类型擦除

    2023-06-11 20:33:10
  • Android中Activity之间跳转和参数传递的实例

    2023-01-31 21:40:32
  • C#装箱与拆箱操作的深入讲解

    2023-04-29 19:10:06
  • Android中ImageView的使用方法

    2023-11-19 02:03:41
  • mybatis-plus分页查询三种方法小结

    2023-11-13 08:44:26
  • 字符串替换Replace仅替换第一个字符串匹配项

    2021-10-02 17:36:56
  • JavaFx Tooltip悬浮提示使用及自定义代码详解

    2023-05-11 15:06:05
  • 完美解决单例设计模式中懒汉式线程安全的问题

    2021-12-30 01:54:21
  • 使用mybatis-plus的insert方法遇到的问题及解决方法(添加时id值不存在异常)

    2023-11-12 19:25:55
  • Android去除烦人的默认闪退Dialog

    2022-07-16 19:56:14
  • C语言中的指针以及二级指针代码详解

    2022-09-04 21:40:28
  • Android常用三方库混淆规则整理(小结)

    2022-09-10 16:35:34
  • Java实现验证码具体代码(图片、汉字)

    2023-03-25 11:14:31
  • 简单了解java自定义和自然排序

    2022-01-29 02:47:26
  • Java如何有效避免SQL注入漏洞的方法总结

    2021-11-22 07:01:54
  • Spring Boot整合Mybatis并完成CRUD操作的实现示例

    2023-11-09 04:36:46
  • asp之家 软件编程 m.aspxhome.com