Android studio进阶开发(三)--socket通信服务的使用

网络通信是我们日常生活中必不可少的,例如QQ和微信,几乎可以通过socket服务器进行连接,以此达到进行实时对话的作用。

服务端的代码(idea):

这里要先开启idea中服务端的接口,从而做到前后端的交互:

package com.socketio.server;

import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;

public class SocketServer {

    public static void main(String[] args) {
        Configuration config = new Configuration();
        // 如果调用了setHostname方法,就只能通过主机名访问,不能通过IP访问
        //config.setHostname("localhost");
        config.setPort(9010); // 设置监听端口
        final SocketIOServer server = new SocketIOServer(config);
        // 添加连接连通的监听事件
        server.addConnectListener(client -> {
            System.out.println(client.getSessionId().toString()+"已连接");
        });
        // 添加连接断开的监听事件
        server.addDisconnectListener(client -> {
            System.out.println(client.getSessionId().toString()+"已断开");
        });
        // 添加文本发送的事件监听器
        server.addEventListener("send_text", String.class, (client, message, ackSender) -> {
            System.out.println(client.getSessionId().toString()+"发送文本消息:"+message);
            client.sendEvent("receive_text", "我已收到,马上做出回应。");
        });
        // 添加图像发送的事件监听器
        server.addEventListener("send_image", JSONObject.class, (client, json, ackSender) -> {
            String desc = String.format("%s,序号为%d", json.getString("name"), json.getIntValue("seq"));
            System.out.println(client.getSessionId().toString()+"发送图片消息:"+desc);
            client.sendEvent("receive_image", json);
        });

        server.start(); // 启动Socket服务
    }

}

注意端口一定要与客户端的一致,这里写的是当你输入内容发送后会自动从服务端中进行回复,未来可通过接入ai(例如讯飞星火)来进行多样式的对话。

客户端代码(Android studio)

1.创建dateuitl,获取当前时间

package com.example.newsoket;

import android.annotation.SuppressLint;

import java.text.SimpleDateFormat;
import java.util.Date;

@SuppressLint("SimpleDateFormat")
public class DateUtil {
    // 获取当前的日期时间
    public static String getNowDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date());
    }

    // 获取当前的时间
    public static String getNowTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(new Date());
    }

    // 获取当前的分钟
    public static String getNowMinute() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        return sdf.format(new Date());
    }

    // 获取当前的时间(精确到毫秒)
    public static String getNowTimeDetail() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        return sdf.format(new Date());
    }

    // 将长整型的时间数值格式化为日期时间字符串
    public static String formatDate(long time) {
        Date date = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

}

2.创建NetConst ,初始化端口和IP地址

package com.example.newsoket;

public class NetConst {
    // HTTP地址的前缀
    public final static String HTTP_PREFIX = "http://192.168.1.7:8080/HttpServer/";
    // WebSocket服务的前缀
    public final static String WEBSOCKET_PREFIX = "ws://192.168.1.7:8080/HttpServer/";
    public final static String BASE_IP = "192.168.1.7"; // 基础Socket服务的ip
    public final static int BASE_PORT = 9010; // 基础Socket服务的端口
    public final static String CHAT_IP = "192.168.1.7"; // 聊天Socket服务的ip
    public final static int CHAT_PORT = 9011; // 聊天Socket服务的端口
}

3.创建SocketUtil 与socket连接进行判断

package com.example.newsoket;

import android.app.Activity;
import android.widget.Toast;

import com.google.gson.Gson;

import org.json.JSONObject;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

import io.socket.client.Socket;

public class SocketUtil {

    // 把对象数据转换为json串,然后发给Socket服务器
    public static void emit(Socket socket, String event, Object obj) {
        try {
            JSONObject json = new JSONObject(new Gson().toJson(obj));
            socket.emit(event, json);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 判断Socket能否连通
    public static void checkSocketAvailable(Activity act, String host, int port) {
        new Thread(() -> {
            try (java.net.Socket socket = new java.net.Socket()) {
                SocketAddress address = new InetSocketAddress(host, port);
                socket.connect(address, 1500);
            } catch (Exception e) {
                e.printStackTrace();
                act.runOnUiThread(() -> {
                    Toast.makeText(act, "无法连接Socket服务器", Toast.LENGTH_SHORT).show();
                });
            }
        }).start();
    }

}

4.创建sockettake.activity进行交互

xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <EditText
        android:id="@+id/et_input"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@drawable/editext_selector"<!可有可无,可以改为自己想要的>
        android:hint="请输入聊天内容"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送文本消息"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <TextView
        android:id="@+id/tv_response"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

java:

package com.example.newsoket;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.newsoket.NetConst;
import com.example.newsoket.DateUtil;
import com.example.newsoket.SocketUtil;

import java.net.URISyntaxException;

import io.socket.client.IO;
import io.socket.client.Socket;

import java.net.URISyntaxException;

public class Sockettext extends AppCompatActivity {

    private static final String TAG = "SocketioTextActivity";
    private EditText et_input; // 声明一个编辑框对象
    private TextView tv_response; // 声明一个文本视图对象
    private Socket mSocket; // 声明一个套接字对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sockettext);
        et_input = findViewById(R.id.et_input);
        tv_response = findViewById(R.id.tv_response);
        findViewById(R.id.btn_send).setOnClickListener(v -> {
            String content = et_input.getText().toString();
            if (TextUtils.isEmpty(content)) {
                Toast.makeText(this, "请输入聊天消息", Toast.LENGTH_SHORT).show();
                return;
            }
            mSocket.emit("send_text", content); // 往Socket服务器发送文本消息
        });
        initSocket(); // 初始化套接字
    }

    // 初始化套接字
    private void initSocket() {
        // 检查能否连上Socket服务器
        SocketUtil.checkSocketAvailable(this, NetConst.BASE_IP, NetConst.BASE_PORT);
        try {
            String uri = String.format("http://%s:%d/", NetConst.BASE_IP, NetConst.BASE_PORT);
            mSocket = IO.socket(uri); // 创建指定地址和端口的套接字实例
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        mSocket.connect(); // 建立Socket连接
        // 等待接收传来的文本消息
        mSocket.on("receive_text", (args) -> {
            String desc = String.format("%s 收到服务端消息:%s",
                    DateUtil.getNowTime(), (String) args[0]);
            runOnUiThread(() -> tv_response.setText(desc));
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSocket.off("receive_text"); // 取消接收传来的文本消息
        if (mSocket.connected()) { // 已经连上Socket服务器
            mSocket.disconnect(); // 断开Socket连接
        }
        mSocket.close(); // 关闭Socket连接
    }
}

这样,一个简单的socket交互就完成了。

尾言

由于作者设备的原因,无论是用真机还是模拟器,客户端都连接不上服务器,所以现在放不出运行图,但是代码是正常运行的,希望有了解前后端交互的伙伴能够帮作者一下,十分感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隐-梵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值