一、基础知识准备

在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解更加顺畅。

1. 网络七层协议

OSI的7层从上到下分别是:7 应用层、 6 表示层、 5 会话层、 4 传输层、 3 网络层、 2 数据链路层、 1 物理层;其中高层(即7、6、5、4层)定义了应用程序的功能,下面3层(即3、2、1层)主要面向通过网络的端到端的数据流。应用层常见的协议有:HTTP、FTP、SMTP等;常见的传输层有:TCP、UDP。本文主要是基于TCP自定义协议实现客户端与服务端的长连接。

2. Socket

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中各类型占字节数

byte      8位,1个字节

boolean   8位,1个字节

char16位,2个字节

short     16位,2个字节

int32位,4个字节

float32位,4个字节

double64位,8个字节

long      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函数,即可看到打印连接成功

1. 客户端

import java.net.Socket;

/**

* Created bymeishanon16/12/1.

*/

publicclass Client {

publicstaticvoid main(String[] args) throws Exception {

boolean isConnected;

String host = "127.0.0.1";

intport = 1122;

Socket socket = null;

try {

socket = SocketFactory.getDefault().createSocket(host, port);

isConnected = true;

System.out.println("连接成功!");

} catch (ConnectException e) {

isConnected = false;

e.printStackTrace();

System.out.println("连接失败!");

}

if (!isConnected) {

return;

}

Thread.sleep(5000);

socket.close();

System.out.println("断开连接!");

}

}

2. 服务端

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

/**

* Created bymeishanon16/12/1.

*/

publicclass Server {

private intport = 1122;

private ServerSocket serverSocket;

publicServer() throws Exception {

serverSocket = new ServerSocket(port, 3);//显式设置连接请求队列的长度为3

System.out.println("服务器启动!");

}

publicvoid service() {

while (true) {

Socket socket = null;

try {

socket = serverSocket.accept();

System.out.println("New connection accepted "+ socket.getInetAddress() +":"+ socket.getPort());

} catch (IOException e) {

e.printStackTrace();

} finally {

if (socket != null) {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

publicstaticvoid main(String[] args) throws Exception {

Server server = new Server();

Thread.sleep(3000);

server.service();

}

}

三、一个简单的自定义协议例子

例子中,数据包的定义:消息对象=包类型+包长度+消息内容

包类型 byte 型

包长度 int 型

消息内容 byte[] 型

1. 客户端

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.net.Socket;

import java.net.UnknownHostException;

import java.util.Scanner;

/**

* Created bymeishanon16/12/1.

*/

publicclass Client {

publicstaticvoid main(String[] args) {

try {

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 staticvoid genProtocol(DataOutputStreamout, String msg) throws IOException {

inttype = 1;                          //消息类型

byte[] bytes = msg.getBytes();         //消息内容

inttotalLen = 1 + 4 + bytes.length;   //消息长度

out.writeByte(type);                   //写入消息类型

out.writeInt(totalLen);                //写入消息长度

out.write(bytes);                      //写入消息内容

out.flush();

}

}

2. 服务端

import java.io.DataInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.ServerSocket;

import java.net.Socket;

/**

* Created bymeishanon16/12/1.

*/

publicclass Server {

publicstaticvoid main(String[] args) {

try {

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 staticvoid parseProtocol(Socket client) throws IOException {

InputStream is= client.getInputStream();

DataInputStream dis = new DataInputStream(is); //读取Java标准数据类型的输入流

//协议解析

while (true) {

byte type = dis.readByte();               //读取消息类型

inttotalLen = 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通信和自定义协议的相关知识点,为后续的深入做一些准备工作,下一篇文章《基于Java Socket的自定义协议,实现Android与服务器的长连接(二)》将通过一个实例来详细讲解自定义协议实现长连接通信。

【编辑推荐】

【责任编辑:枯木 TEL:(010)68476606】

点赞 0

java android长连接_基于Java Socket的自定义协议,实现Android与服务器的长连接(一)...相关推荐

  1. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  2. java游戏开发毕业论文_基于JAVA的五子游戏的开发设计毕业论文

    基于JAVA的五子游戏的开发设计毕业论文 毕业论文基于 JAVA 的五子游戏的开发设计山东凯文科技职业学院摘 要人工智能是一门正在迅速发展的新兴的,综合性很强的交叉科学.它与生物工程.空间技术一起被并 ...

  3. java管理系统中期报告_基于Java的图书馆管理系统的设计-中期报告

    基于Java的图书馆管理系统的设计-中期报告 毕业设计(论文)中期报告 毕业设计(论文)题目:基于Java的图书馆管理系统的设计 专业:计算机 学生信息: 指导教师信息: 报告提交日期:2012年5月 ...

  4. 基于java的ftp客户端_基于Java的FTP客户端软件的设计

    基于的FTP客户端软件的设计(含选题审批表,任务书,开题报告,中期检查表,毕业论文8600字,答辩记录) 摘 要:FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中 ...

  5. java农产品查询系统_基于java的农产品销售系统的设计与实现论文.docx

    基于java的农产品销售系统的设计与实现论文.docx 分类号_______________ 密级________________ UDC _______________ 学号_毕业设计(论文)论文题 ...

  6. java版五子棋分析_基于JAVA的五子棋游戏系统设计实现分析.doc

    WORD格式整理版 WORD格式整理版 学习好帮手 学习好帮手 基于JAVA的五子棋游戏系统设计与实现 专 业 电子信息工程 学 生 董永杰 指导教师 曾玉 WORD格式整理版 学习好帮手 摘 要 目 ...

  7. java网页作业提交_基于JAVA网上作业提交批改系统的设计(SQL)(含录像)

    基于JAVA网上作业提交批改系统的设计(SQL)(含录像)(毕业论文15000字,程序代码,SQLserver数据库) 摘  要 随着社会的进步,网络技术的发展为教育界提供了一片崭新的空间,传统的教学 ...

  8. 扫雷java程序算法设计_基于Java的Windows扫雷游戏的设计与实现毕业论文+任务书+翻译及原文+源码+辅导视频...

    基于Java的Windows扫雷游戏的设计与实现 摘 要 扫雷这款游戏有着很长的历史,从扫雷被开发出来到现在进行了无数次的优化,这款游戏变得越来越让人爱不释手了,简单的玩法在加上一个好看的游戏界面,每 ...

  9. java超市系统论文_基于JAVA的超市进销存管理系统毕业论文.doc

    word文档 可自由复制编辑 摘 要 由于超市行业的竞争越来越强,超市规模的发展不断扩大,商品数量和种类急剧增加,有关商品的信息量也随之增长.超市随时都需要对商品各种信息进行统计分析. 超市销售管理系 ...

最新文章

  1. POJ 1189 记忆化搜索
  2. Vue教程1 【Vue核心】
  3. Spring3.2.0-mybatis3.2.0 基于全注解搭建的后台框架-基础版
  4. 七问唐骏:真的性格好就能成功?
  5. python打开火狐浏览器打不开网页_PHP让指定网页只能在微信内置浏览器打开 附代码...
  6. 利用C语言实现计算机图像处理的方法
  7. 如何提高UDP的可靠性
  8. 什么叫做罗列式_极简罗列法怎么写作文
  9. 一文读懂VictoriaMetrics集群方案
  10. python数据可视化编程实战 第2版 github_Python数据可视化编程实战(三):在Mac OS X上安装matplotlib...
  11. java 中方法里的参数_【Java基础】12、java中方法的参数传递机制
  12. 【技术分享】BurpSuite 代理设置的小技巧
  13. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_01 File类_1_File类的概述
  14. JavaScript高级教程(面向对象编程)
  15. 捷联惯导系统学习4.2(捷联惯导误差方程)
  16. SCRT中只换行不回车的问题(阶梯)
  17. IDEA中JDBC连接MYSQL数据库步骤超详细总结
  18. 皮尔逊相关系数_皮尔逊相关系数(Person)
  19. 【CSS】学习iview的icon样式+font字体
  20. dbt-tidb 1.2.0 尝鲜

热门文章

  1. mybatis3.1-[topic-16-17]-映射文件_增删改查_insert_获取自增主键的值
  2. 剑指offer_第一个只出现一次的字符
  3. iOS推送(利用极光推送)
  4. How to create and apply a patch with Git
  5. WPF调用图片路径,或资源图片
  6. 比较字符串是否相同,比较大小
  7. Android(java)学习笔记164:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例)...
  8. 对于小波分解和傅立叶分解的理解
  9. MVC 配置路由 反复走控制其中的action (int?)
  10. jqurey ajax 的动态添加二级联动下拉菜单