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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • django debug_eclipse使用debug调试

    django debug_eclipse使用debug调试介绍Django框架的调试工具栏使用django-debug-toolbar库,是一组可配置的面板,显示有关当前请求/响应的各种调试信息,点击时,显示有关面板内容的更多详细信息。应用1.安装

    2022年7月31日
    7
  • linux修改密码永久有效[通俗易懂]

    linux修改密码永久有效[通俗易懂]password-X99999用户名称passwd用户名称

    2025年9月17日
    5
  • 牛客国庆集训派对Day6 I.清明梦超能力者黄YY(树剖)「建议收藏」

    牛客国庆集训派对Day6 I.清明梦超能力者黄YY(树剖)「建议收藏」题目:https://www.nowcoder.com/acm/contest/206/I正难则反。问你倒数第k次的颜色,正着来搞不定,那就转换成“倒着来的第k次”。使用树剖将这棵树丢进线段树里,不维护染色,而是维护更新的次数(因为除了倒数第k次的颜色,其他的根本没用啊!!!),然后把区间最小值pushUp到树顶。更新完染色次数之后,用树顶来判整个区间里是否存在已经被更新了k次的节点,如果…

    2022年7月14日
    21
  • 机器学习—决策树原理(python代码实现)

    机器学习—决策树原理(python代码实现)首先,决策树(DecisionTree)是一种基本的分类与回归方法,在这里主要讨论用于分类的决策树。决策树的学习通常包含三个步骤:特征选择,决策树的生成,决策树的剪枝。优点:计算复杂度不高,输出结果易于理解,对中间值的缺失值不敏感,可以处理不相关特征数据。 缺点:可能会产生过度匹配的问题。 使用数据类型:数值型和标称型。那么具体的来通过一个例子说明一下决策树。下面这个例子是通过贷款…

    2025年10月3日
    4
  • Bitmap.MakeTransparent 方法

    Bitmap.MakeTransparent 方法使默认的透明颜色对此Bitmap透明。重载列表使默认的透明颜色对此Bitmap对象透明。[Visual Basic]OverloadsPublicSubMakeTransparent()[C#]publicvoidMakeTransparent();[C++]public:voidMakeTransparent();[JScript]publicfunctionM

    2022年7月21日
    14
  • tga文件格式(波形声音文件格式)

    Tga常见的格式有非压缩RGB和压缩RGB两种格式,文件的第三个Byte位作为标记:2为非压缩RGB格式,10为压缩RGB格式。这里的类只实现读取非压缩格式的tga文件。先给出tga文件的文件格式:名称偏移长度说明图像信息字段长度01本字段是1字节无符号整型,指出图像信息字

    2022年4月10日
    63

发表回复

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

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