当前位置: 首页 > 科技观察

基于JavaSocket的自定义协议,实现Android与服务器的长连接(一)

时间:2023-03-23 10:42:50 科技观察

1.基础知识准备基础介绍,这些知识点虽然我们在学校学过,但难免忘掉.这里先简单介绍一下,以便更顺利的理解后面的文字内容。1、OSI的七层,从上到下依次为:7个应用层、6个表示层、5个会话层、4个传输层、3个网络层、2个数据链路层、1个物理层;即第7、6、5、4层定义了应用程序的功能,后面的三层(即第3、2、1层)主要面向端到端的数据流经网络。应用层常见的协议有:HTTP、FTP、SMTP等;常见的传输层包括:TCP、UDP。本文主要基于TCP自定义协议实现客户端与服务端的长连接。2、SocketSocket本质上是一个编程接口(API)。它封装了TCP/IP,TCP/IP也为程序员做网络开发提供了接口。这就是Socket编程接口,通常也叫“socket”。.socket之间的连接过程可以分为三个步骤:客户端请求,服务器回复并接收,客户端收到服务器的回复,即三次握手。当连接成功后,应用程序的两端都会生成一个Socket实例,操作这个实例来完成需要的会话。对于一个网络连接来说,sockets是平等的,没有区别,也没有因为是在server端还是在client端的高低之分。3、比特、字节“比特”是电子计算机中最小的数据单位。每个位的状态只能是0或1;“字节”由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中每种类型占用byte8位,1byteboolean8位,1bytechar16位,2bytesshort16位,2bytesint32位,4bytesfloat32位,4Bytedouble64位,8byteslong64位,8字节6.SocketJavaSocket构造函数中的相关函数,intport,InetAddresslocalAddress,intlocalPort)throwsIOExceptionSocket也可以通过以下方式生成://远程服务器的IP地址getPort();//远程服务器的端口getLocalAddress();//本地客户端的IP地址getLocalPort();//本地客户端端口getInputStream();//获取输入流getOutStream();//获取输出流Socket状态isClosed();//连接是否关闭,如果关闭则返回true;否则返回false吨();//如果曾经连接则返回true;否则返回falseisBound();//如果Socket已经绑定到本地端口,则返回true;否则返回false判断Socket的状态是否连接booleanisConnected=socket.isConnected()&&!socket.isClosed();//判断当前是否连接ServerSocket构造函数ServerSocket()throwsIOExceptionServerSocket(intport)throwsIOExceptionServerSocket(intport,intbacklog)throwsIOExceptionServerSocket(intport,intbacklog,InetAddressbindAddr)throwsIOException服务器收到客户端的连接请求:Socketsocket=serverSocket.accept();7.普通流操作类输入流InputStreamJava中的抽象类,描述了从字节数组读取的流输入可序列化接口)DataInputStreamm包含读取Java标准数据类型的输入流和输出流的抽象类OutputStream,描述流的输入流。字节数组输出流。写入字节数组的输出流。缓冲输出流。缓冲的输出流。该对象必须实现Serializable接口)DataOutputStream包含用于编写Java标准数据类型的输出流。打印连接成功1.客户端importjava.net.Socket;/***Createdbymeishanon16/12/1.*/publicclassClient{publicstaticvoidmain(String[]args)throwsException{booleanisConnected;Stringhost="127.0.0.1";intport=1122;Socketsocket=null;try{socket=SocketFactory.getDefault().createSocket(host,port);isConnected=true;System.out.println("连接成功!");}catch(ConnectExceptione){isConnected=false;e.printStackTrace();System.out.println("连接失败!");}if(!isConnected){return;}Thread.sleep(5000);socket.close();System.out.println(“断开连接!”);}}2。Serverimportjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;/***Createdbymeishanon16/12/1.*/publicclassServer{privateintport=1122;私人服务器套接字服务器套接字;publicServer()throwsException{serverSocket=newServerSocket(port,3);//显式设置连接请求队列长度为3System.out.println("Serverstart!");}publicvoidservice(){while(true){Socketsocket=null;try{socket=serverSocket.accept();System.out.println("Newconnectionaccepted"+socket.getInetAddress()+":"+socket.getPort());}catch(IOExceptione){e.printStackTrace();}finally{if(socket!=null){try{socket.close();}catch(IOExceptione){e.printStackTrace();}}}}}publicstaticvoidmain(String[]args)throwsException{Serverserver=newServer();Thread.sleep(3000);server.service();}}3.一个简单的自定义协议示例示例中数据包的定义:消息对象=包类型+包长度+消息内容包类型经过tetypepacketlengthinttypemessagecontentbyte[]type1.clientimportjava.io.DataOutputStream;importjava.io.IOException;importjava.io.OutputStream;importjava.net.Socket;importjava.net.UnknownHostException;importjava.util。Scanner;/***Createdbymeishanon16/12/1.*/publicclassClient{publicstaticvoidmain(String[]args){try{Socketclient=newSocket("127.0.0.1",9091);OutputStreamout=client.getOutputStream();DataOutputStreamouts=newDataOutputStream(出去);while(true){Scannerscanner=newScanner(System.in);genProtocol(outs,scanner.next());}}catch(UnknownHostExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}/***构造协议**@paramout*@parammsg*@throwsIOException*/privatestaticvoidgenProtocol(DataOutputStreamout,Stringmsg)throwsIOException{inttype=1;//消息类型byte[]bytes=msg.getBytes();//消息内容inttotalLen=1+4+bytes.length;//消息长度out.writeByte(type);//写入消息类型out.writeInt(totalLen);//写入消息长度out.write(bytes);//写入消息内容out.flush();}}2.serverimportjava.io.DataInputStream;importjava.io.IOException;importjava.io.InputStream;importjava.net.ServerSocket;importjava.net.Socket;/***Createdbymeishanon16/12/1.*/publicclassServer{publicstaticvoidmain(String[]args){try{ServerSocketserver=newServerSocket(9091);while(true){Socketclient=server.accept();System.out.println("client"+client.getRemoteSocketAddress()+"连接成功");parseProtocol(client);}}catch(IOExceptione){e.printStackTrace();}}/***消息解析**@paramclient*@throwsIOException*/privatestaticvoidparseProtocol(Socketclient)throwsIOException{InputStreamis=client.getInputStream();DataInputStreamdis=newDataInputStream(is);//读取取Java标准数据类型的输入流//协议分析while(true){bytetype=dis.readByte();//读取消息类型inttotalLen=dis.readInt();//读取消息长度byte[]data=newbyte[totalLen-4-1];//定义存放消息内容的字节数组dis.readFully(data);//读取消息内容Stringmsg=newString(data);//消息内容System.out.println("Receivedm消息类型“+类型”;System.out.println("接收消息长度"+totalLen);System.out.println("发送的内容是:"+msg);}}}4.总结本文简单介绍学习了socket通信和自定义协议的相关知识点,为后续做一些准备。下一篇《基于Java Socket的自定义协议,实现Android与服务器的长连接(二)》将通过实例详细讲解自定义协议实现长连接通信

最新推荐
猜你喜欢