Android的TCP Socket连接组件

Android的TCP Socket连接组件

https://github.com/Sopage/android-network

https://github.com/Sopage/DreamSocket

package android.net.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

/**
 * Socket连接操作类
 * 
 * @author Esa
 */
public class SocketBase {

	private Socket mSocket;// socket连接对象
	private DataOutputStream out;
	private DataInputStream in;// 输入流
	private SocketCallback callback;// 信息回调接口
	private int timeOut = 1000 * 30;

	/**
	 * 构造方法传入信息回调接口对象
	 * 
	 * @param sdi
	 *            回调接口
	 */
	public SocketBase(SocketCallback callback) {
		this.callback = callback;
	}

	/**
	 * 连接网络服务器
	 * 
	 * @throws UnknownHostException
	 * @throws IOException
	 */
	public void connect(String ip, int port) throws Exception {
		mSocket = new Socket();
		SocketAddress address = new InetSocketAddress(ip, port);
		mSocket.connect(address, timeOut);// 连接指定IP和端口
		if (mSocket.isConnected()) {
			out = new DataOutputStream(mSocket.getOutputStream());// 获取网络输出流
			in = new DataInputStream(mSocket.getInputStream());// 获取网络输入流
			callback.connected();
		}
	}

	public void setTimeOut(int timeOut) {
		this.timeOut = timeOut;
	}

	/**
	 * 返回连接服是否成功
	 * 
	 * @return
	 */
	public boolean isConnected() {
		if(mSocket != null){
			return mSocket.isConnected();
		}
		return false;
	}

	/**
	 * 发送数据
	 * 
	 * @param buffer
	 *            信息字节数据
	 * @throws IOException
	 */
	public void write(byte[] buffer) throws IOException {
		if (out != null) {
			out.write(buffer);
			out.flush();
		}
	}

	/**
	 * 断开连接
	 * 
	 * @throws IOException
	 */
	public void disconnect() {
		try {
			if (mSocket != null) {
				if (!mSocket.isInputShutdown()) {
					mSocket.shutdownInput();
				}
				if (!mSocket.isOutputShutdown()) {
					mSocket.shutdownOutput();
				}
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
				mSocket.close();// 关闭socket
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			callback.disconnect();
			out = null;
			in = null;
			mSocket = null;// 制空socket对象
		}
	}

	/**
	 * 读取网络数据
	 * 
	 * @throws IOException
	 */
	public void read() throws IOException {
		if (in != null) {
			byte[] buffer = new byte[1024*1];// 缓冲区字节数组,信息不能大于此缓冲区
			byte[] tmpBuffer;// 临时缓冲区
			int len = 0;// 读取长度
			while ((len = in.read(buffer)) > 0) {
				tmpBuffer = new byte[len];// 创建临时缓冲区
				System.arraycopy(buffer, 0, tmpBuffer, 0, len);// 将数据拷贝到临时缓冲区
				callback.receive(tmpBuffer);// 调用回调接口传入得到的数据
				tmpBuffer = null;
			}
		}
	}
}
package android.net.tcp;

import java.util.Vector;

/**
 * 连接服务器线程类
 * 
 * @author Esa
 */
public class SocketConnect implements Runnable {

	private boolean isConnect = false;// 是否连接服务器
	private boolean isWrite = false;// 是否发送数据
	private static final Vector<byte[]> datas = new Vector<byte[]>();// 待发送数据队列
	private SocketBase mSocket;// socket连接
	private WriteRunnable writeRunnable;// 发送数据线程
	private String ip = null;
	private int port = -1;

	/**
	 * 创建连接
	 * 
	 * @param callback
	 *            回调接口
	 */
	public SocketConnect(SocketCallback callback) {
		mSocket = new SocketBase(callback);// 创建socket连接
		writeRunnable = new WriteRunnable();// 创建发送线程
	}

	@Override
	public void run() {
		if (ip == null || port == -1) {
			throw new NullPointerException("not set address");
		}
		isConnect = true;
		while (isConnect) {
			synchronized (this) {
				try {
					mSocket.connect(ip, port);// 连接服务器
				} catch (Exception e) {
					try {
						mSocket.disconnect();// 断开连接
						this.wait(6000);
						continue;
					} catch (InterruptedException e1) {
						continue;
					}
				}
			}
			isWrite = true;// 设置可发送数据
			new Thread(writeRunnable).start();// 启动发送线程
			try {
				mSocket.read();// 获取数据
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				writeRunnable.stop();
				mSocket.disconnect();
			}
		}
	}

	/**
	 * 关闭服务器连接
	 */
	public synchronized void disconnect() {
		isConnect = false;
		this.notify();
		resetConnect();
	}

	/**
	 * 重置连接
	 */
	public void resetConnect() {
		writeRunnable.stop();// 发送停止信息
		mSocket.disconnect();
	}

	/**
	 * 向发送线程写入发送数据
	 */
	public void write(byte[] buffer) {
		writeRunnable.write(buffer);
	}

	/**
	 * 设置IP和端口
	 * 
	 * @param ip
	 * @param port
	 */
	public void setRemoteAddress(String host, int port) {
		this.ip = host;
		this.port = port;
	}

	/**
	 * 发送数据
	 */
	private boolean writes(byte[] buffer) {
		try {
			mSocket.write(buffer);
			return true;
		} catch (Exception e) {
			resetConnect();
		}
		return false;
	}

	/**
	 * 发送线程
	 * 
	 * @author Esa
	 */
	private class WriteRunnable implements Runnable {

		@Override
		public void run() {
			System.out.println(">TCP发送线程开启<");
			while (isWrite) {
				synchronized (this) {
					if (datas.size() <= 0) {
						try {
							this.wait();// 等待发送数据
						} catch (InterruptedException e) {
							continue;
						}
					}
					while (datas.size() > 0) {
						byte[] buffer = datas.remove(0);// 获取一条发送数据
						if (isWrite) {
							writes(buffer);// 发送数据
						} else {
							this.notify();
						}
					}
				}
			}
			System.out.println(">TCP发送线程结束<");
		}

		/**
		 * 添加数据到发送队列
		 * 
		 * @param buffer
		 *            数据字节
		 */
		public synchronized void write(byte[] buffer) {
			datas.add(buffer);// 将发送数据添加到发送队列
			this.notify();// 取消等待
		}

		public synchronized void stop() {
			isWrite = false;
			this.notify();
		}
	}
}
package android.net.tcp;

/**
 * 获取网络数据回调类
 * 
 * @author Esa
 * 
 */
public abstract interface SocketCallback {
	
	/**
	 * 当建立连接是的回调
	 */
	public abstract void connected();

	/**
	 * 当获取网络数据回调接口
	 * 
	 * @param buffer
	 *            字节数据
	 */
	public abstract void receive(byte[] buffer);

	/**
	 * 当断开连接的回调
	 */
	public abstract void disconnect();

}
//使用方法
		SocketConnect connect = new SocketConnect(new SocketCallback() {
			
			@Override
			public void receive(byte[] buffer) {
				System.out.println("Server Message :" + new String(buffer));
			}
			
			@Override
			public void disconnect() {
				
			}
			
			@Override
			public void connected() {
				
			}
		});
		connect.setRemoteAddress("localhost", 11011);
		new Thread(connect).start();
		for(int i=0; i<100; i++){
			connect.write("test".getBytes());
			Thread.sleep(1000);
		}

 

转载于:https://my.oschina.net/hes/blog/158404

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110030.html原文链接:https://javaforall.net

(0)
上一篇 2021年8月25日 下午8:00
下一篇 2021年8月25日 下午8:00


相关推荐

  • 记一次遇到挖矿程序的经历「建议收藏」

    记一次遇到挖矿程序的经历「建议收藏」就在几天前,遇到了一次挖矿程序偷偷装在ECS阿里云服务器上的经历。那是一个风和日丽的上午,我和往常一样来到公司,倒杯水等待电脑打开,之后打开日常维护的几个系统。结果其中有一个OA系统,发现无法正常打开。一开始我以为是网络问题,但是发现打开其他网站正常,于是登上服务器准备探个究竟。登陆云服务器后,重启OA服务,发现报错,报错提示连接线程池连接不上。根据提示,怀疑是连不上部署在本地的数据服…

    2022年4月20日
    44
  • CPU的流水线指令设计

    CPU的流水线指令设计为什么小小一个 CPU 有那么多周期 Cycle 程序的性能 是由三个因素相乘来衡量的 指令数 CPI 时钟周期 和周期相关的只有一个时钟周期 即 CPU 主频的倒数 一个 CPU 的时钟周期可以认为是可以完成一条最简单的计算机指令的时间 那为何构造 CPU 时 有那么多周期 单指令周期处理器一条 CPU 指令的执行 由 FDE 三步组成 这个执行过程 至少需花费一个时钟周期 因为在取指令的时候 我们需要通过时钟周期的信号 来决定计数器的自增 很自然 我们希望能确保让这样一整条指令的执行 在一个时钟周期内完成

    2026年3月16日
    2
  • linux指令popd,Linux切换目录pushd、popd、dirs命令

    linux指令popd,Linux切换目录pushd、popd、dirs命令Linux 切换目录 pushd popd dirs 命令 pushd 和 popd 在 linux 中可以用来方便地在多个目录之间切换 切换目录虽然有一点复杂 在实际中 发现通过使用 pushd 和 popd 能够极大地提高效率 cd 表示返回当前用户的默认目录 cd 表示回到之前的目录 cqs centos7share pushd boot grub boot grub usr share data

    2025年11月29日
    4
  • n8n安装图解教程:小白也能轻松上手

    n8n安装图解教程:小白也能轻松上手

    2026年3月15日
    2
  • Java递归写法_java递归调用

    Java递归写法_java递归调用递归是自己调用自己,java里的递归写法如下:/** *1*2*(n-1)*n的计算形式,使用递归实现 *@authorAdministrator * */publicclassDiGui{//初始化变量,不能使用默认值privatestaticlongresult=1;/***非递归方式*@paramn*@retu

    2026年1月16日
    6
  • 电子元器件品牌及其代理商

    电子元器件品牌及其代理商海思(Hisilicon)在大中华区的授权分销商有:深圳市群方电子、深圳市淇诺实业、晓龙国际、威健实业、中国电子器材、深圳市智宇鹏电子等。 紫光在大中华区的授权分销商包括:Arrow,中豪,力同科技,泰发科电子,普浩国际,Mornsun,国华,厦门建益达,昱博科技,CEACSZ,WPG等。 全志科技在大中华区的授权分销商有:君行科技,蓝欣电子,易新泰科技,方糖电子等。 兆易创新(Giga…

    2022年6月29日
    89

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号