日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java TCP/IP Socket 编程 笔记

發布時間:2024/4/17 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java TCP/IP Socket 编程 笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://jimmee.iteye.com/blog/617110

http://jimmee.iteye.com/category/93740

Java TCP/IP Socket 編程 筆記(一)—基本概念

  • 博客分類:
  • J2SE
編程SocketJava網絡協議網絡應用 一些概念:
通信信道(communication channel):將字節序列從一個主機傳輸到另一個主機的一種手段,可能是有線電纜,如以太網(Ethernet),也可能是無線的,如WiFi,或是其他方式的連接。

信息(information)是指由程序創建和解釋的字節序列。在計算機網絡環境中,這些字節序列稱為分組報文(packet)。

協議(protocol)相當于相互通信的程序達成的一種約定,它規定了分組報文的交換方式和它們包含的意義。一組協議規定了分組報文的結構(例如報文中的哪一部分表明了目的地址)以及怎樣對報文中所包含的信息進行解析。

TCP和UDP屬于傳輸層,IP屬于網絡層,TCP,UDP和IP的具體實現通常駐留在主機的操作系統中。應用程序通過套接字API對UDP協議和TCP協議所提供的服務進行訪問。

IP協議提供了一種數據報服務:每組分組報文都由網絡獨立處理和分發,就像信件或包裹通過郵政系統發送一樣。IP報文必須包含一個保存其目的地址的字段,就像你所投遞的每份包裹都寫明了收件人地址一樣。

TCP協議和UDP協議使用的地址叫做端口號,都是用來區分同一主機中的不同應用程序的。

客戶端(client)是通信的發起者,而服務器(server)程序則被動等待客戶端發起通信,并對其作出響應。

一個程序是作為客戶端還是服務器,決定了它在與其對等端(peer)建立通信時使用的套接字API(客戶端的對等端是服務器,反之亦然)。客服端必須首先知道服務器端的地址和端口號,反之則不需要。這個打電話類似。只要通信連接建立成功,服務器和客戶端之間就沒有區別了。


Socket(套接字)是一種抽象層,應用程序通過它來發送和接受數據,就像應用程序打開一個文件句柄,將數據讀寫到穩定的存儲器上一樣。一個TCP/IP套接字由一個互聯網地址,一個端對端協議(TCP或UDP協議)以及一個端口號唯一確定。

?

Java TCP/IP Socket 編程 筆記(二)—TCP的例子

  • 博客分類:
  • J2SE
編程SocketJava網絡協議 1.InetAddress類和SocketAddress用于識別網絡主機
TCP協議客戶端和服務器端的套接字為Socket和ServerSocket
UDP協議的客戶端和服務器端的套接字為DatagramSocket

2.
類 NetworkInterface表示一個由名稱和分配給此接口的 IP 地址列表組成的網絡接口,其getNetworkInterfaces()返回此機器上的所有接口。getInetAddresses()是返回一個 Enumeration 并將所有 InetAddress 或 InetAddress 的子集綁定到此網絡接口的便捷方法。(注意:一個網絡接口可能包含IPv4或IPv6地址)

3.類 InetAddress的getHostAddress()返回 IP 地址字符串(以文本表現形式)。 getAllByName(String host)在給定主機名的情況下,根據系統上配置的名稱服務返回其 IP 地址所組成的數組。getHostName()獲取此 IP 地址的主機名。getHostAddress() 返回 IP 地址字符串(以文本表現形式)。

4.TCP套接字
服務器端ServerSocket實例監聽TCP鏈接請求,并為每個請求創建新的Socket實例。也就是說,服務器端要同時處理ServerSocket實例和Sockete實例,而客戶端只需要使用Socket實例。

TCP客戶端:
Java代碼 ?
  • public?class?TCPEchoClient?{ ??
  • ????public?static?void?main(String?[]?args)?throws?UnknownHostException,?IOException,?InterruptedException?{ ??
  • ????????if(args.length<2||args.length>3){ ??
  • ????????????throw?new?IllegalArgumentException("Parameter(s):<Server>?<Word>?[<Port>]"); ??
  • ????????} ??
  • ???????? ??
  • ????????String?server=args[0]; ??
  • ???????? ??
  • ????????byte?[]?data=args[1].getBytes(); ??
  • ???????? ??
  • ????????int?servPort=(args.length==3)?Integer.parseInt(args[2]):7; ??
  • ???????? ??
  • ????????//1.創建一個Socket實例:構造函數向指定的遠程主機和端口建立一個TCP連接 ??
  • ????????Socket?socket=new?Socket(server,servPort); ??
  • ????????System.out.println("Connected?to?server...?sending?echo?string"); ??
  • ???????? ??
  • ????????/** ?
  • ?????????*2.?通過套接字的輸入輸出流進行通信:一個Socket連接實例包括一個InputStream和一個OutputStream,它們的用法同于其他Java輸入輸出流。 ?
  • ?????????*/??
  • ????????InputStream?in=socket.getInputStream(); ??
  • ????????OutputStream?out=socket.getOutputStream(); ??
  • ???????? ??
  • ????????out.write(data); ??
  • ???????? ??
  • ????????int?totalBytesRcvd=0; ??
  • ????????int?bytesRcvd; ??
  • ???????? ??
  • ????????while(totalBytesRcvd<data.length){ ??
  • ????????????if((bytesRcvd=in.read(data,?totalBytesRcvd,?data.length-totalBytesRcvd))==-1){ ??
  • ????????????????throw?new?SocketException("Connection?closed?prematurely"); ??
  • ????????????} ??
  • ????????????totalBytesRcvd+=bytesRcvd; ??
  • ????????} ??
  • ????????System.out.println("Receved:?"+new?String(data)); ??
  • ???????? ??
  • ????????//3.使用Socet類的close()方法關閉連接 ??
  • ????????socket.close(); ??
  • ????} ??
  • }??
  • public class TCPEchoClient {public static void main(String [] args) throws UnknownHostException, IOException, InterruptedException {if(args.length<2||args.length>3){throw new IllegalArgumentException("Parameter(s):<Server> <Word> [<Port>]");}String server=args[0];byte [] data=args[1].getBytes();int servPort=(args.length==3)?Integer.parseInt(args[2]):7;//1.創建一個Socket實例:構造函數向指定的遠程主機和端口建立一個TCP連接Socket socket=new Socket(server,servPort);System.out.println("Connected to server... sending echo string");/***2. 通過套接字的輸入輸出流進行通信:一個Socket連接實例包括一個InputStream和一個OutputStream,它們的用法同于其他Java輸入輸出流。*/InputStream in=socket.getInputStream();OutputStream out=socket.getOutputStream();out.write(data);int totalBytesRcvd=0;int bytesRcvd;while(totalBytesRcvd<data.length){if((bytesRcvd=in.read(data, totalBytesRcvd, data.length-totalBytesRcvd))==-1){throw new SocketException("Connection closed prematurely");}totalBytesRcvd+=bytesRcvd;}System.out.println("Receved: "+new String(data));//3.使用Socet類的close()方法關閉連接socket.close();} }

    TCP服務器端代碼:
    Java代碼 ?
  • public?class?TCPEchoServer?{ ??
  • ????private?static?final?int?BUFSIZE=32; ??
  • ???? ??
  • ????public?static?void?main(String?[]?args)?throws?IOException,?InterruptedException{ ??
  • ????????if(args.length!=1){ ??
  • ????????????throw?new?IllegalArgumentException("Parameter(s):<Port>"); ??
  • ????????} ??
  • ???????? ??
  • ????????int?servPort=Integer.parseInt(args[0]); ??
  • ???????? ??
  • ????????//1.創建一個ServerSocket實例并制定本地端口。此套接字的功能是偵聽該制定端口收到的連接。 ??
  • ????????ServerSocket?servSock=new?ServerSocket(servPort); ??
  • ???????? ??
  • ????????int?recvMsgSize; ??
  • ???????? ??
  • ????????byte?[]?receiveBuf=new?byte[BUFSIZE]; ??
  • ???????? ??
  • ????????//2.重復執行 ??
  • ????????while(true){ ??
  • ????????????//a.調用ServerSocket的accept()方法以獲取下一個客戶端連接。 ??
  • ????????????//基于新建立的客戶端連接,創建一個Socket實例,并由accept()方法返回 ??
  • ????????????Socket?clntSock=servSock.accept(); ??
  • ????????????SocketAddress?clientAddress=clntSock.getRemoteSocketAddress(); ??
  • ????????????System.out.println("Handling?client?at?"+clientAddress); ??
  • ???????????? ??
  • ????????????//b,使用所返回的Socket實例的InputStream和OutputStream與客戶端進行通信 ??
  • ????????????InputStream?in=clntSock.getInputStream(); ??
  • ????????????OutputStream?out=clntSock.getOutputStream(); ??
  • ??
  • ????????????while((recvMsgSize=in.read(receiveBuf))!=-1){ ??
  • ????????????????out.write(receiveBuf,?0,?recvMsgSize); ??
  • ????????????} ??
  • ???????? ??
  • ????????????//c,通信完成后,使用Socket的close()方法關閉該客戶端套接字鏈接 ??
  • ????????????clntSock.close(); ??
  • ????????} ??
  • ????} ??
  • }??
  • Java TCP/IP Socket 編程 筆記(三)—UDP的例子

    ?

    1.UDP套接字與TCP套接字不同。UDP套接字在使用前不需要進行連接。TCP協議與電話通信相似,而UDP協議則與郵件通信相似:你寄包裹或信件時不要進行“連接”,但是你的為每個包裹和信件制定目的地址。類似地,每條信息(datagram,即數據報文)負載了自己的地址信息,并與其他信息相互獨立。在接收信息時,UDP套接字扮演的角色就像是一個信箱,從不同地址發送來的信件和包裹都可以放到里面。一旦被創建,UDP套接字就可以用來連續地向不同的地址發送消息,或從任何地址接收信息。
    UDP套接字將保留邊界信息。UDP不像TCP一樣,它是盡可能地傳送消息,但并不保證信息一定能成功到達目的地址,而且信息到達的順序與其發送順序不一定一致(就像通過郵政部分寄信一樣)。因此,UDP套接字的程序必須準備好處理信息的丟失和重排。
    UDP的優點之一是效率較高,其次是靈活性。

    Java通過DatagramPacket類和DatagramSocket類來使用UDP套接字。客戶端和服務端都使用DatagramSocket來發送數據,使用DatagramPacket來接收數據。

    發送信息時,Java程序創建一個包含了待發送信息的DatagramPacket實例,并將其作為參數傳遞給DatagramSocket類的send()方法。接收信息時,Java程序首先創建一個DatagramPacket類的實例,該實例中預先分配了一些空間(一個字節數組byte[]),并將接收到的信息存放在該空間中。然后把該實例作為參數傳遞給DatagramSocket類的receive()方法。


    DatagramPacket的內部有length和offset字段,如果指定了offset,數據報文的數據部分將從字節數組的指定位置發送或接收數據。length參數指定了字節數組中在發送時要傳輸的字節數,活在接收數據時所能接收的最多字節數。length要比data.length小,但不能比它大。

    UDP客戶端:

    Java代碼 ?
  • import?java.io.IOException; ??
  • import?java.io.InterruptedIOException; ??
  • import?java.net.DatagramPacket; ??
  • import?java.net.DatagramSocket; ??
  • import?java.net.InetAddress; ??
  • ??
  • public?class?UDPEchoClientTimeout?{ ??
  • ????private?static?final?int?TIMEOUT=3000; ??
  • ????private?static?final?int?MAXTRIES=5; ??
  • ???? ??
  • ????public?static?void?main(String[]?args)?throws?IOException?{ ??
  • ????????if(args.length<2||args.length>3){ ??
  • ????????????throw?new?IllegalArgumentException("Parameter(s):<Server>?<Word>?[<Port>]"); ??
  • ????????} ??
  • ???????? ??
  • ????????InetAddress?serverAddress=InetAddress.getByName(args[0]);//server?address; ??
  • ????????byte?[]?bytesToSend=args[1].getBytes(); ??
  • ????????int?servPort=(args.length==3)?Integer.parseInt(args[2]):7; ??
  • ???????? ??
  • ????????//1.創建一個DatagramSocket實例,可以選擇對本地地址和端口進行設置。? ??
  • ????????DatagramSocket?socket=new?DatagramSocket(); ??
  • ????????//設置receive()方法的最長阻塞時間 ??
  • ????????socket.setSoTimeout(TIMEOUT); ??
  • ???????? ??
  • ????????DatagramPacket?sendPacket=new?DatagramPacket(bytesToSend,bytesToSend.length,serverAddress,servPort); ??
  • ????????DatagramPacket?receivePacket=new?DatagramPacket(new?byte[bytesToSend.length],bytesToSend.length); ??
  • ???????? ??
  • ????????int?tries=0; ??
  • ????????boolean?receivedResponse=false; ??
  • ???????? ??
  • ????????do{ ??
  • ????????????//2.使用DatagramSocket類的send()和receive()方法來發送和接收DatagramPacket實例,進行通信 ??
  • ????????????socket.send(sendPacket); ??
  • ????????????try{ ??
  • ????????????????socket.receive(receivePacket); ??
  • ????????????????if(!receivePacket.getAddress().equals(serverAddress)){ ??
  • ????????????????????throw?new?IOException("Received?packet?from?an?unknown?source"); ??
  • ????????????????} ??
  • ????????????????receivedResponse=true; ??
  • ????????????}catch(InterruptedIOException?e){ ??
  • ????????????????tries+=1; ??
  • ????????????????System.out.println("Timed?out,"+(MAXTRIES-tries)+"?more?tries?..."); ??
  • ????????????} ??
  • ???????????? ??
  • ????????}while(!receivedResponse&&(tries<MAXTRIES)); ??
  • ???????? ??
  • ???????? ??
  • ????????if(receivedResponse){ ??
  • ????????????System.out.println("Received:?"+new?String(receivePacket.getData())); ??
  • ????????}else{ ??
  • ????????????System.out.println("No?response?--?giving?up."); ??
  • ????????} ??
  • ???????? ??
  • ????????//3.通信完成后,使用DatagramSocket類的close方法來銷毀該套接字 ??
  • ????????socket.close(); ??
  • ????} ??
  • }??
  • import java.io.IOException; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;public class UDPEchoClientTimeout {private static final int TIMEOUT=3000;private static final int MAXTRIES=5;public static void main(String[] args) throws IOException {if(args.length<2||args.length>3){throw new IllegalArgumentException("Parameter(s):<Server> <Word> [<Port>]");}InetAddress serverAddress=InetAddress.getByName(args[0]);//server address;byte [] bytesToSend=args[1].getBytes();int servPort=(args.length==3)?Integer.parseInt(args[2]):7;//1.創建一個DatagramSocket實例,可以選擇對本地地址和端口進行設置。 DatagramSocket socket=new DatagramSocket();//設置receive()方法的最長阻塞時間socket.setSoTimeout(TIMEOUT);DatagramPacket sendPacket=new DatagramPacket(bytesToSend,bytesToSend.length,serverAddress,servPort);DatagramPacket receivePacket=new DatagramPacket(new byte[bytesToSend.length],bytesToSend.length);int tries=0;boolean receivedResponse=false;do{//2.使用DatagramSocket類的send()和receive()方法來發送和接收DatagramPacket實例,進行通信socket.send(sendPacket);try{socket.receive(receivePacket);if(!receivePacket.getAddress().equals(serverAddress)){throw new IOException("Received packet from an unknown source");}receivedResponse=true;}catch(InterruptedIOException e){tries+=1;System.out.println("Timed out,"+(MAXTRIES-tries)+" more tries ...");}}while(!receivedResponse&&(tries<MAXTRIES));if(receivedResponse){System.out.println("Received: "+new String(receivePacket.getData()));}else{System.out.println("No response -- giving up.");}//3.通信完成后,使用DatagramSocket類的close方法來銷毀該套接字socket.close();} }



    UDP的服務器端:

    Java代碼 ?
  • import?java.io.IOException; ??
  • import?java.net.DatagramPacket; ??
  • import?java.net.DatagramSocket; ??
  • ??
  • public?class?UDPEchoServer?{ ??
  • ????private?static?final?int?ECHOMAX=255;//max?size?of?echo?datagram ??
  • ???? ??
  • ????public?static?void?main(String[]?args)?throws?IOException?{ ??
  • ????????if(args.length!=1){ ??
  • ????????????throw?new?IllegalArgumentException("Parameter(s):<Port>"); ??
  • ????????} ??
  • ???????? ??
  • ????????int?servPort=Integer.parseInt(args[0]); ??
  • ???????? ??
  • ????????//1.創建一個DatagramSocket實例,指定本地端口號,可以選擇指定本地地址 ??
  • ????????DatagramSocket?socket=new?DatagramSocket(servPort); ??
  • ????????DatagramPacket?packet=new?DatagramPacket(new?byte[ECHOMAX],ECHOMAX); ??
  • ???????? ??
  • ????????while(true){ ??
  • ????????????//2.使用DatagramSocket的receive方法來接收一個DatagramPacket實例。 ??
  • ????????????socket.receive(packet); ??
  • ????????????System.out.println("Handling?client?at?"+packet.getAddress().getHostAddress()+"?on?port?"+packet.getPort()); ??
  • ???????????? ??
  • ????????????socket.send(packet); ??
  • ????????????packet.setLength(ECHOMAX); ??
  • ????????} ??
  • ????} ??
  • }??
  • import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;public class UDPEchoServer {private static final int ECHOMAX=255;//max size of echo datagrampublic static void main(String[] args) throws IOException {if(args.length!=1){throw new IllegalArgumentException("Parameter(s):<Port>");}int servPort=Integer.parseInt(args[0]);//1.創建一個DatagramSocket實例,指定本地端口號,可以選擇指定本地地址DatagramSocket socket=new DatagramSocket(servPort);DatagramPacket packet=new DatagramPacket(new byte[ECHOMAX],ECHOMAX);while(true){//2.使用DatagramSocket的receive方法來接收一個DatagramPacket實例。socket.receive(packet);System.out.println("Handling client at "+packet.getAddress().getHostAddress()+" on port "+packet.getPort());socket.send(packet);packet.setLength(ECHOMAX);}} }



    注意:DatagramPacket的getData()方法的使用,它返回數據緩沖區,是一個字節數組,需要注意。
    ? packet.setData(buf, offset,length);設置了接收數據時放到緩存去buf中的位置
    ,因此接收的數據new String(packet.getData(),packet.getOffset(),packet.getLength())的方式構造的。

    ?

    Java TCP/IP Socket 編程 筆記(四)—發送和接收數據

    • 博客分類:
    • J2SE
    編程JavaSocket 1.TCP/IP協議要求信息必須在塊(chunk)中發送和接收,而塊的長度必須是8位的倍數,因此,我們可以認為TCP/IP協議中傳輸的信息是字節序列。如何發送和解析信息需要一定的應用程序協議。
    2.信息編碼:
    ??? 首先是Java里對基本整型的處理,發送時,要注意:1)每種數據類型的字節個數;2)這些字節的發送順序是怎樣的?(little-endian還是big-endian);3)所傳輸的數值是有符號的(signed)還是無符號的(unsigned)。具體編碼時采用位操作(移位和屏蔽)就可以了。具體在Java里,可以采用DataOutputStream類和ByteArrayOutputStream來實現。恢復時可以采用DataInputStream類和ByteArrayInputStream類。
    ??? 其次,字符串和文本,在一組符號與一組整數之間的映射稱為編碼字符集(coded character set)。發送者與接收者必須在符號與整數的映射方式上達成共識,才能使用文本信息進行通信,最簡單的方法就是定義一個標準字符集。具體編碼時采用String的getBytes()方法。
    ??? 最后,位操作。如果設置一個特定的設為1,先設置好掩碼(mask),之后用或操作;要清空特定一位,用與操作。
    3.成幀與解析
    成幀(framing)技術解決了接收端如何定位消息的首位位置的問題。
    如果接收者試圖從套接字中讀取比消息本身更多的字節,將可能發生以下兩種情況之一:如果信道中沒有其他消息,接收者將阻塞等待,同時無法處理接收到的消息;如果發送者也在等待接收端的響應消息,則會形成死鎖(dealock);另一方面,如果信道中還有其他消息,則接收者會將后面消息的一部分甚至全部讀到第一條消息中去,這將產生一些協議錯誤。因此,在使用TCP套接字時,成幀就是一個非常重要的考慮因素。
    有兩個技術:
    1. 基于定界符(Delimiter-based):消息的結束由一個唯一的標記(unique marker)指出,即發送者在傳輸完數據后顯式添加的一個特殊字節序列。這個特殊標記不能在傳輸的數據中出現。幸運的是,填充(stuffing)技術能夠對消息中出現的定界符進行修改,從而使接收者不將其識別為定界符。在接收者掃描定界符時,還能識別出修改過的數據,并在輸出消息中對其進行還原,從而使其與原始消息一致。
    2. 顯式長度(Explicit length):在變長字段或消息前附加一個固定大小的字段,用來指示該字段或消息中包含了多少字節。這種方法要確定消息長度的上限,以確定保存這個長度需要的字節數。
    接口:
    Java代碼 ?
  • import?java.io.IOException; ??
  • import?java.io.OutputStream; ??
  • ??
  • public?interface?Framer?{ ??
  • ????void?frameMsg(byte?[]?message,OutputStream?out)?throws?IOException; ??
  • ????byte?[]?nextMsg()?throws?IOException; ??
  • }??
  • import java.io.IOException; import java.io.OutputStream;public interface Framer {void frameMsg(byte [] message,OutputStream out) throws IOException;byte [] nextMsg() throws IOException; }
    定界符的方式:
    Java代碼 ?
  • import?java.io.ByteArrayOutputStream; ??
  • import?java.io.EOFException; ??
  • import?java.io.IOException; ??
  • import?java.io.InputStream; ??
  • import?java.io.OutputStream; ??
  • ??
  • public?class?DelimFramer?implements?Framer?{ ??
  • ????private?InputStream?in;//data?source; ??
  • ????private?static?final?byte?DELIMTER=(byte)'\n';//message?delimiter ??
  • ???? ??
  • ????public?DelimFramer(InputStream?in){ ??
  • ????????this.in=in; ??
  • ????} ??
  • ??
  • ????@Override??
  • ????public?void?frameMsg(byte[]?message,?OutputStream?out)?throws?IOException?{ ??
  • ????????//ensure?that?the?message?dose?not?contain?the?delimiter ??
  • ????????for(byte?b:message){ ??
  • ????????????if(b==DELIMTER) ??
  • ????????????????throw?new?IOException("Message?contains?delimiter"); ??
  • ????????} ??
  • ????????out.write(message); ??
  • ????????out.write(DELIMTER); ??
  • ????????out.flush(); ??
  • ???????? ??
  • ???????? ??
  • ????} ??
  • ??
  • ????@Override??
  • ????public?byte[]?nextMsg()?throws?IOException?{ ??
  • ????????ByteArrayOutputStream?messageBuffer=new?ByteArrayOutputStream(); ??
  • ????????int?nextByte; ??
  • ???????? ??
  • ????????while((nextByte=in.read())!=DELIMTER){ ??
  • ????????????if(nextByte==-1){//end?of?stream? ??
  • ????????????????if(messageBuffer.size()==0){ ??
  • ????????????????????return?null; ??
  • ????????????????}else{ ??
  • ????????????????????throw?new?EOFException("Non-empty?message?without?delimiter"); ??
  • ????????????????} ??
  • ????????????} ??
  • ????????????messageBuffer.write(nextByte); ??
  • ????????} ??
  • ????????return?messageBuffer.toByteArray(); ??
  • ????} ??
  • }??
  • import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;public class DelimFramer implements Framer {private InputStream in;//data source;private static final byte DELIMTER=(byte)'\n';//message delimiterpublic DelimFramer(InputStream in){this.in=in;}@Overridepublic void frameMsg(byte[] message, OutputStream out) throws IOException {//ensure that the message dose not contain the delimiterfor(byte b:message){if(b==DELIMTER)throw new IOException("Message contains delimiter");}out.write(message);out.write(DELIMTER);out.flush();}@Overridepublic byte[] nextMsg() throws IOException {ByteArrayOutputStream messageBuffer=new ByteArrayOutputStream();int nextByte;while((nextByte=in.read())!=DELIMTER){if(nextByte==-1){//end of stream?if(messageBuffer.size()==0){return null;}else{throw new EOFException("Non-empty message without delimiter");}}messageBuffer.write(nextByte);}return messageBuffer.toByteArray();} }
    顯式長度方法:
    Java代碼 ?
  • import?java.io.DataInputStream; ??
  • import?java.io.EOFException; ??
  • import?java.io.IOException; ??
  • import?java.io.InputStream; ??
  • import?java.io.OutputStream; ??
  • ??
  • public?class?LengthFramer?implements?Framer?{ ??
  • ????public?static?final?int?MAXMESSAGELENGTH=65535; ??
  • ????public?static?final?int?BYTEMASK=0xff; ??
  • ????public?static?final?int?SHOTMASK=0xffff; ??
  • ????public?static?final?int?BYTESHIFT=8; ??
  • ???? ??
  • ????private?DataInputStream?in;//?wrapper?for?data?I/O ??
  • ???? ??
  • ????public?LengthFramer(InputStream?in)?throws?IOException{ ??
  • ????????this.in=new?DataInputStream(in); ??
  • ????} ??
  • ??
  • ????@Override??
  • ????public?void?frameMsg(byte[]?message,?OutputStream?out)?throws?IOException?{ ??
  • ????????if(message.length>MAXMESSAGELENGTH){ ??
  • ????????????throw?new?IOException("message?too?long"); ??
  • ????????} ??
  • ???????? ??
  • ????????//write?length?prefix ??
  • ????????out.write((message.length>>BYTEMASK)&BYTEMASK); ??
  • ????????out.write(message.length&BYTEMASK); ??
  • ????????//write?message ??
  • ????????out.write(message); ??
  • ????????out.flush(); ??
  • ????} ??
  • ??
  • ????@Override??
  • ????public?byte[]?nextMsg()?throws?IOException?{ ??
  • ????????int?length; ??
  • ???????? ??
  • ????????try{ ??
  • ????????????length=in.readUnsignedShort(); ??
  • ????????}catch(EOFException?e){ ??
  • ????????????//no?(or?1?byte)?message; ??
  • ????????????return?null; ??
  • ????????} ??
  • ????????//0<=length<=65535; ??
  • ????????byte?[]?msg=new?byte[length]; ??
  • ????????in.readFully(msg);//if?exception,it's?a?framing?error; ??
  • ????????return?msg; ??
  • ????} ??
  • }??
  • ?

    總結

    以上是生活随笔為你收集整理的Java TCP/IP Socket 编程 笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。