如何干净的毁尸灭迹实现Android/Java Socket 长连接通信

在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
标签:至少1个,最多5个
原文地址:
一、基础知识准备
在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解更加顺畅。
1. 网络七层协议
OSI的7层从上到下分别是:7 应用层、 6 表示层、 5 会话层、 4 传输层、 3 网络层、 2 数据链路层、 1 物理层;其中高层(即7、6、5、4层)定义了应用程序的功能,下面3层(即3、2、1层)主要面向通过网络的端到端的数据流。应用层常见的协议有:HTTP、FTP、SMTP等;常见的传输层有:TCP、UDP。本文主要是基于TCP自定义协议实现客户端与服务端的长连接。
Socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口,通常也称作"套接字"。套接字之间的连接过程可以分为三个步骤:客户端请求,服务端回复收到,客户端收到服务端的回复,即三次握手。连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。
3. 位(bit)、字节(byte)
“位(bit)”是电子计算机中最小的数据单位。每一位的状态只能是0或1;“字节(Byte)”由8个二进制位构成(即1byte=8bit),它是存储空间的基本计量单位,它能表示到数值范围为0到255(即2的8次方减1);
4. 算术移位运算(符号位不变,低位补0)
左移运算:1&&2,1的二进制位是1,向左移两位是100,转为十进制数即为4,所以1&&2的运算结果是4;
右移运算:7&&2,7的二进制位是111,向右移两位是1,所以7&&2的运算结果是1 。
5. Java中各类型占字节数
8位,1个字节
8位,1个字节
16位,2个字节
16位,2个字节
32位,4个字节
32位,4个字节
64位,8个字节
64位,8个字节
6. Java中socket相关函数
Socket构造函数
Socket(InetAddress address, int port)throws UnknownHostException, IOException
Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException
Socket(String host, int port)throws UnknownHostException, IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException
还可以通过以下方式生成socket:
SocketFactory.getDefault().createSocket(String address, String port) throws ConnectException
Socket方法
getInetAddress();
// 远程服务端的IP地址
getPort();
// 远程服务端的端口
getLocalAddress();
// 本地客户端的IP地址
getLocalPort();
// 本地客户端的端口
getInputStream();
// 获得输入流
getOutStream();
// 获得输出流
Socket状态
isClosed();
// 连接是否已关闭,若关闭,返回true;否则返回false
isConnect();
// 如果曾经连接过,返回true;否则返回false
isBound();
// 如果Socket已经与本地一个端口绑定,返回true;否则返回false
判断Socket的状态是否处于连接中
boolean isConnected = socket.isConnected() && !socket.isClosed();
// 判断当前是否处于连接
ServerSocket构造函数
ServerSocket()throws IOException
ServerSocket(int port)throws IOException
ServerSocket(int port, int backlog)throws IOException
ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException
服务端接收客户端的连接请求:
Socket socket = serverSocket.accept();
7. Java中常见流操作类
InputStream
抽象类,描述流的输入
ByteArrayInputStream
从字节数组读取的输入流
BufferedInputStream
缓冲输入流
FileInputStream
从文件读入的输入流
ObjectInputStream
对象输入流(所读写的对象必须实现Serializable接口)
DataInputStream
包含了读取Java标准数据类型的输入流
OutputStream
抽象类,描述流的输入
ByteArrayOutputStream
写入字节数组的输出流
BufferedOutputStream
缓冲输出流
FileOutputStream
写入文件的输出流
ObjectOutputStream
对象输出流(所读写的对象必须实现Serializable接口)
DataOutputStream
包含了写Java标准数据类型的输出流
二、一个简单的socket连接例子
注:先运行服务端代码的main函数,再运行客户端代码的main函数,即可看到打印连接成功
import java.net.S
* Created by meishan on 16/12/1.
public class Client {
public static void main(String[] args) throws Exception {
boolean isC
String host = "127.0.0.1";
int port = 1122;
Socket socket =
socket = SocketFactory.getDefault().createSocket(host, port);
isConnected =
System.out.println("连接成功!");
} catch (ConnectException e) {
isConnected =
e.printStackTrace();
System.out.println("连接失败!");
if (!isConnected) {
Thread.sleep(5000);
socket.close();
System.out.println("断开连接!");
import java.io.IOE
import java.net.ServerS
import java.net.S
* Created by meishan on 16/12/1.
public class Server {
private int port = 1122;
private ServerSocket serverS
public Server() throws Exception {
serverSocket = new ServerSocket(port, 3);//显式设置连接请求队列的长度为3
System.out.println("服务器启动!");
public void service() {
while (true) {
Socket socket =
socket = serverSocket.accept();
System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
socket.close();
} catch (IOException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Server server = new Server();
Thread.sleep(3000);
server.service();
三、一个简单的自定义协议例子
例子中,数据包的定义:消息对象=包类型+包长度+消息内容
包类型 byte 型
包长度 int 型
消息内容 byte[] 型
import java.io.DataOutputS
import java.io.IOE
import java.io.OutputS
import java.net.S
import java.net.UnknownHostE
import java.util.S
* Created by meishan on 16/12/1.
public class Client {
public static void main(String[] args) {
Socket client = new Socket("127.0.0.1", 9091);
OutputStream out = client.getOutputStream();
DataOutputStream outs = new DataOutputStream(out);
while (true) {
Scanner scaner = new Scanner(System.in);
genProtocol(outs, scaner.next());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
* 构造协议
* @param out
* @param msg
* @throws IOException
private static void genProtocol(DataOutputStream out, String msg) throws IOException {
int type = 1;
//消息类型
byte[] bytes = msg.getBytes();
//消息内容
int totalLen = 1 + 4 + bytes.
//消息长度
out.writeByte(type);
//写入消息类型
out.writeInt(totalLen);
//写入消息长度
out.write(bytes);
//写入消息内容
out.flush();
import java.io.DataInputS
import java.io.IOE
import java.io.InputS
import java.net.ServerS
import java.net.S
* Created by meishan on 16/12/1.
public class Server {
public static void main(String[] args) {
ServerSocket server = new ServerSocket(9091);
while (true) {
Socket client = server.accept();
System.out.println("客户端" + client.getRemoteSocketAddress() + "连接成功");
parseProtocol(client);
} catch (IOException e) {
e.printStackTrace();
* 消息解析
* @param client
* @throws IOException
private static void parseProtocol(Socket client) throws IOException {
InputStream is = client.getInputStream();
DataInputStream dis = new DataInputStream(is); //读取Java标准数据类型的输入流
//协议解析
while (true) {
byte type = dis.readByte();
//读取消息类型
int totalLen = dis.readInt();
//读取消息长度
byte[] data = new byte[totalLen - 4 - 1]; //定义存放消息内容的字节数组
dis.readFully(data);
//读取消息内容
String msg = new String(data);
//消息内容
System.out.println("接收消息类型" + type);
System.out.println("接收消息长度" + totalLen);
System.out.println("发来的内容是:" + msg);
本文简单介绍了socket通信和自定义协议的相关知识点,为后续的深入做一些准备工作,下一篇文章将通过一个实例来详细讲解自定义协议实现长连接通信。
0 收藏&&|&&4
你可能感兴趣的文章
5 收藏,516
190 收藏,1.7k
本作品采用 署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。如何干净的实现Android/Java Socket 长连接通信_百度知道
如何干净的实现Android/Java Socket 长连接通信
我有更好的答案
io/" target="_blank">http:<a href="http://netty://nettynetty.官方网址
为您推荐:
其他类似问题
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。2016年10月 移动开发大版内专家分月排行榜第二2016年9月 移动开发大版内专家分月排行榜第二
2016年8月 移动开发大版内专家分月排行榜第三
2016年10月 移动开发大版内专家分月排行榜第二2016年9月 移动开发大版内专家分月排行榜第二
2016年8月 移动开发大版内专家分月排行榜第三
2016年10月 移动开发大版内专家分月排行榜第二2016年9月 移动开发大版内专家分月排行榜第二
2016年8月 移动开发大版内专家分月排行榜第三
匿名用户不能发表回复!|如何干净的实现Android&#47;Java Socket 长连接通信_百度知道
如何干净的实现Android&#47;Java Socket 长连接通信
我有更好的答案
你需要一个线程池管理你的socket连接,网上例子多着呢,快去搜吧另外说一点,android与后台交互很多情况下使用http方式
为您推荐:
android的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
CSDN &《程序员》研发主编,投稿&纠错等事宜请致邮
你只管努力,剩下的交给时光!
如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。个人网站:www.xttblog.com。个人QQ群:、
个人大数据技术博客:http://www.iteblog.com
javaweb中使用socket通信

我要回帖

更多关于 如何干净的毁尸灭迹 的文章

 

随机推荐