1.TCP通信
netty
一、依赖配置
在build.gradle中配置最新Netty依赖:
dependencies {
implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}
二、基本使用
1. 封装工具类
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class NettyClient {
private static final int RECONNECT_DELAY = 3; // 重连间隔(秒)
private EventLoopGroup workerGroup;
private Channel channel;
private final String host;
private final int port;
private NettyListener listener;
public NettyClient(String host, int port) {
this.host = host;
this.port = port;
}
// 初始化连接
public void connect() {
workerGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder()); // 字符串解码
pipeline.addLast(new StringEncoder()); // 字符串编码
pipeline.addLast(new ClientHandler(listener)); // 业务处理器
}
});
// 异步连接
ChannelFuture future = bootstrap.connect(host, port).addListener((ChannelFutureListener) f -> {
if (!f.isSuccess()) scheduleReconnect(); // 连接失败触发重连
});
channel = future.sync().channel();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 消息发送
public void sendMessage(String msg) {
if (channel != null && channel.isActive()) {
channel.writeAndFlush(msg);
}
}
// 重连机制
private void scheduleReconnect() {
workerGroup.schedule(this::connect, RECONNECT_DELAY, TimeUnit.SECONDS);
}
// 释放资源
public void shutdown() {
if (channel != null) channel.close();
if (workerGroup != null) {
Future<?> future = workerGroup.shutdownGracefully();
future.syncUninterruptibly();
}
}
// 设置消息监听器
public void setListener(NettyListener listener) {
this.listener = listener;
}
// 内部处理器
private static class ClientHandler extends SimpleChannelInboundHandler<String> {
private final NettyListener listener;
ClientHandler(NettyListener listener) {
this.listener = listener;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
if (listener != null) listener.onMessageReceived(msg); // 消息回调
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
if (listener != null) listener.onConnectionStatusChanged(true); // 连接建立
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
if (listener != null) listener.onConnectionStatusChanged(false); // 连接断开
}
}
// 状态监听接口
public interface NettyListener {
void onMessageReceived(String message);
void onConnectionStatusChanged(boolean isConnected);
}
}
2. Activity调用示例
public class MainActivity extends AppCompatActivity implements NettyClient.NettyListener {
private NettyClient nettyClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化Netty客户端
nettyClient = new NettyClient("192.168.1.100", 8080);
nettyClient.setListener(this);
new Thread(() -> nettyClient.connect()).start(); // 在子线程启动连接
// 发送消息示例
findViewById(R.id.btn_send).setOnClickListener(v -> {
String msg = "Hello Server!";
nettyClient.sendMessage(msg);
});
}
// 实现监听回调
@Override
public void onMessageReceived(final String message) {
runOnUiThread(() -> {
TextView tv = findViewById(R.id.tv_response);
tv.setText("收到: " + message); // 主线程更新UI
});
}
@Override
public void onConnectionStatusChanged(final boolean isConnected) {
runOnUiThread(() -> {
String status = isConnected ? "已连接" : "连接断开";
Toast.makeText(this, "状态: " + status, Toast.LENGTH_SHORT).show();
});
}
@Override
protected void onDestroy() {
nettyClient.shutdown(); // 释放资源防止内存泄漏
super.onDestroy();
}
}
4.心跳保活
在ClientHandler中添加:
// 每30秒发送心跳
ctx.executor().scheduleAtFixedRate(() ->
ctx.writeAndFlush("HEARTBEAT"), 0, 30, TimeUnit.SECONDS
);
2.UDP通信
netty
一、依赖配置
在build.gradle中配置最新Netty依赖:
dependencies {
implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}
二、基本使用
1. UDP工具类封装
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Netty UDP 客户端工具类
* 功能:消息发送、接收回调、资源释放
*/
public class UdpClient {
private final Bootstrap bootstrap;
private final NioEventLoopGroup group;
private Channel channel;
private final ExecutorService threadPool;
private UdpListener listener;
public UdpClient() {
group = new NioEventLoopGroup();
bootstrap = new Bootstrap();
threadPool = Executors.newSingleThreadExecutor();
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true) // 支持广播
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
protected void initChannel(NioDatagramChannel ch) {
ch.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
// 主线程回调 → 子线程处理
threadPool.execute(() -> {
String msg = packet.content().toString(CharsetUtil.UTF_8);
if (listener != null) {
listener.onMessageReceived(msg);
}
});
}
});
}
});
}
/**
* 绑定本地端口(Android需动态申请端口)
* @param port 本地端口(0表示随机端口)
*/
public void bind(int port) {
threadPool.execute(() -> {
try {
ChannelFuture future = bootstrap.bind(port).sync();
channel = future.channel();
if (listener != null) listener.onBindSuccess(port);
} catch (Exception e) {
if (listener != null) listener.onError(e);
}
});
}
/**
* 发送消息
* @param targetIp 目标IP
* @param targetPort 目标端口
* @param message 消息内容
*/
public void send(String targetIp, int targetPort, String message) {
if (channel == null || !channel.isActive()) return;
threadPool.execute(() -> {
try {
ByteBuf buf = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
InetSocketAddress target = new InetSocketAddress(targetIp, targetPort);
channel.writeAndFlush(new DatagramPacket(buf, target));
} catch (Exception e) {
if (listener != null) listener.onError(e);
}
});
}
/**
* 释放资源
*/
public void shutdown() {
if (channel != null) channel.close();
group.shutdownGracefully();
threadPool.shutdown();
}
/**
* 设置事件监听
*/
public void setListener(UdpListener listener) {
this.listener = listener;
}
public interface UdpListener {
void onBindSuccess(int localPort); // 绑定成功
void onMessageReceived(String msg); // 收到消息
void onError(Throwable cause); // 发生异常
}
}
2. Activity调用示例
public class MainActivity extends AppCompatActivity implements UdpClient.UdpListener {
private UdpClient udpClient;
private TextView tvStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvStatus = findViewById(R.id.tv_status);
// 1. 初始化UDP客户端
udpClient = new UdpClient();
udpClient.setListener(this);
udpClient.bind(0); // 绑定随机端口
// 2. 发送消息示例
findViewById(R.id.btn_send).setOnClickListener(v -> {
String ip = "192.168.1.100"; // 目标服务器IP
int port = 8080; // 目标服务器端口
String msg = "Hello UDP!";
udpClient.send(ip, port, msg);
});
}
// 3. 实现监听回调
@Override
public void onBindSuccess(final int localPort) {
runOnUiThread(() -> tvStatus.setText("本地端口: " + localPort));
}
@Override
public void onMessageReceived(final String msg) {
runOnUiThread(() -> Toast.makeText(this, "收到: " + msg, Toast.LENGTH_SHORT).show());
}
@Override
public void onError(final Throwable cause) {
runOnUiThread(() -> tvStatus.setText("错误: " + cause.getMessage()));
}
@Override
protected void onDestroy() {
udpClient.shutdown(); // 释放资源
super.onDestroy();
}
}
3.注意权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
4.注意
Android 9+ 默认禁用UDP广播,需在代码中开启:
bootstrap.option(ChannelOption.SO_BROADCAST, true);
3.WebService
ksoap2-android
一、依赖配置
在build.gradle中配置最新Netty依赖:
implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'
二、基本使用
1. 封装工具类
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SoapClientUtil {
private static final String DEFAULT_NAMESPACE = "http://example.com/";
private static final String DEFAULT_URL = "http://example.com/soap-endpoint";
private static final int THREAD_POOL_SIZE = 5;
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
// 异步请求(推荐)
public static void callAsync(String methodName, Map<String, Object> params,
boolean isDotNet, SoapCallback callback) {
threadPool.submit(() -> {
try {
Object result = callSync(methodName, params, isDotNet);
callback.onSuccess(result);
} catch (Exception e) {
callback.onError(e);
}
});
}
// 同步请求
public static Object callSync(String methodName, Map<String, Object> params,
boolean isDotNet) throws Exception {
SoapObject request = new SoapObject(DEFAULT_NAMESPACE, methodName);
// 添加请求参数
if (params != null) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
request.addProperty(entry.getKey(), entry.getValue());
}
}
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
envelope.dotNet = isDotNet; // 适配 .NET 平台
HttpTransportSE transport = new HttpTransportSE(DEFAULT_URL);
transport.debug = true; // 开启调试日志
try {
transport.call(DEFAULT_NAMESPACE + methodName, envelope);
return envelope.getResponse(); // 返回原始响应(可转为 SoapObject/String)
} catch (Exception e) {
throw new RuntimeException("SOAP请求失败: " + e.getMessage());
}
}
// 回调接口
public interface SoapCallback {
void onSuccess(Object result);
void onError(Exception e);
}
}
2. Activity调用示例
// 初始化参数
String methodName = "getWeather";
Map<String, Object> params = new HashMap<>();
params.put("cityName", "Beijing");
boolean isDotNet = true; // .NET 服务需设为 true
// 发起异步请求
SoapClientUtil.callAsync(methodName, params, isDotNet, new SoapClientUtil.SoapCallback() {
@Override
public void onSuccess(Object result) {
if (result instanceof SoapObject) {
SoapObject response = (SoapObject) result;
String temperature = response.getPropertyAsString("temperature");
String weather = response.getPropertyAsString("weather");
Log.d("SOAP", "北京天气: " + weather + ",温度: " + temperature);
}
}
@Override
public void onError(Exception e) {
Log.e("SOAP", "请求失败: " + e.getMessage());
}
});
473

被折叠的 条评论
为什么被折叠?



