欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

androidSocket實現(xiàn)簡單聊天功能以及文件傳輸

干程序是一件枯燥重復(fù)的事,每當感到內(nèi)心浮躁的時候,我就會找小說來看。我從小就喜愛看武俠小說,一直有著武俠夢。從金庸,古龍,梁羽生系列到鳳歌(昆侖),孫曉(英雄志)以及蕭鼎的(誅仙)讓我領(lǐng)略著不一樣的江湖。

創(chuàng)新互聯(lián)專注于坡頭網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供坡頭營銷型網(wǎng)站建設(shè),坡頭網(wǎng)站制作、坡頭網(wǎng)頁設(shè)計、坡頭網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造坡頭網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供坡頭網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

如果你有好看的武俠系列小說,給我留言哦。題外話就扯這么多了,接著還是上技術(shù)。

看看今天實現(xiàn)的功能效果圖:

android Socket實現(xiàn)簡單聊天功能以及文件傳輸

可以這里使用多臺手機進行通訊,我采用的服務(wù)器發(fā)送消息。

是不是只有發(fā)送消息,有些顯得太單調(diào)了。好,在發(fā)送消息的基礎(chǔ)上增加文件傳輸。后期會增加視頻,音頻的傳輸,增加表情包。那一起來看看圖文消息的效果圖,帶領(lǐng)大家一起來實現(xiàn)通訊的簡易聊天功能。

android Socket實現(xiàn)簡單聊天功能以及文件傳輸

需要解決的難點:

如何判斷socket接收的數(shù)據(jù)是字符串還是流?

如果你已是一名老司機,還請留言給出寶貴意見。帶著這個疑問我們接著往下看。

Socket概述

Socket我們稱之為"套接字",用于消息通知系統(tǒng)(如:激光推送),時事通訊系統(tǒng)(如:環(huán)信)等等。用于描述IP地址和端口,是一個通信鏈的句柄。網(wǎng)絡(luò)上的兩個程序通過一個雙向的通訊連接實現(xiàn)數(shù)據(jù)的交換,這個雙向鏈路的一端稱為一個Socket,一個Socket由一個IP地址和一個端口號唯一確定(如:ServerSocket)。應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求。Socket是TCP/IP協(xié)議的一個十分流行的編程界面,但是,Socket所支持的協(xié)議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯(lián)系的。在Java環(huán)境下,Socket編程主要是指基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程。

java.net包下有兩個類:Socket和ServerSocket,基于TCP協(xié)議。

本文針對Socket和ServerSocket作主要講解。

socket連接

建立Socket連接至少需要一對套接字,其中一個運行于客戶端,稱為ClientSocket ,另一個運行于服務(wù)器端,稱為ServerSocket。

套接字之間的連接過程分為三個步驟:服務(wù)器監(jiān)聽,客戶端請求,連接確認。步驟如下:

  • 服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請求
  • 客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求。
  • 連接確認:當服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時,就響應(yīng)客戶端套接字的請求,建立一個新的線程,把服務(wù)器端套接字的描述發(fā)給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求。

JDK Socket

在java.net包下有兩個類:Socket和ServerSocket。ServerSocket用于服務(wù)器端,Socket是建立網(wǎng)絡(luò)連接時使用的。在連接成功時,應(yīng)用程序兩端都會產(chǎn)生一個Socket實例,操作這個實例,完成所需的會話。對于一個網(wǎng)絡(luò)連接來說,套接字是平等的,并沒有差別,不因為在服務(wù)器端或在客戶端而產(chǎn)生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。接著了解下Socket和ServerSocket的構(gòu)造方法。

Socket

Socket的構(gòu)造方法:

Socket(InetAddress address,int port); //創(chuàng)建一個流套接字并將其連接到指定 IP 地址的指定端口號
Socket(String host,int port); //創(chuàng)建一個流套接字并將其連接到指定主機上的指定端口號
Socket(InetAddress address,int port, InetAddress localAddr,int localPort); //創(chuàng)建一個套接字并將其連接到指定遠程地址上的指定遠程端口
Socket(String host,int port, InetAddress localAddr,int localPort); //創(chuàng)建一個套接字并將其連接到指定遠程主機上的指定遠程端口
Socket(SocketImpl impl); //使用用戶指定的 SocketImpl 創(chuàng)建一個未連接 Socket

參數(shù)含義:

  • address 雙向連接中另一方的IP地址
  • port 端口號
  • localPort 本地主機端口號
  • localAddr 本地機器地址
  • impl 是socket的父類,既可以用來創(chuàng)建serverSocket又可以用來創(chuàng)建Socket

注意:我們在選取端口號的時候需要特別注意,每一個端口提供一種特定的服務(wù),只有給出正確的端口,才能獲得相應(yīng)的服務(wù)。0~1023的端口號為系統(tǒng)所保留,例如http服務(wù)的端口號為80,telnet服務(wù)的端口號為21,ftp服務(wù)的端口號為23。本文選取的端口號為30003

Socket的幾個重要方法:

public InputStream getInputStream(); //方法獲得網(wǎng)絡(luò)連接輸入,同時返回一個IutputStream對象實例
public OutputStream getOutputStream(); //方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例
public Socket accept(); //用于產(chǎn)生"阻塞",直到接受到一個連接,并且返回一個客戶端的Socket對象實例。

對流的操作,操作完記得處理和關(guān)閉。以及對流異常的處理。

ServerSocket

ServerSocket的構(gòu)造方法:

ServerSocket(int port); //創(chuàng)建綁定到特定端口的服務(wù)器套接字
ServerSocket(int port,int backlog); //利用指定的 backlog 創(chuàng)建服務(wù)器套接字并將其綁定到指定的本地端口號
ServerSocket(int port,int backlog, InetAddress bindAddr); //使用指定的端口、偵聽 backlog 和要綁定到的本地 IP地址創(chuàng)建服務(wù)器

接著我們一起來看看案例。

發(fā)送和接收消息

首先來實現(xiàn)一個簡單的案例,服務(wù)器端一直監(jiān)聽某個端口,等待客戶端連接請求??蛻舳烁鶕?jù)IP地址和端口號連接服務(wù)器端,接著客服端通過控制臺向服務(wù)端發(fā)送消息,服務(wù)端接收到消息并且展示出來。下面來看看具體實現(xiàn)的步驟:

ClientSocket客服端:

    try {
      Socket socket = new Socket("173.1.1.121", 30004);

      //獲取控制臺輸入的內(nèi)容
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
      System.out.print("請輸入發(fā)送的字符串:");
      String str = bufferedReader.readLine();

      //給服務(wù)端發(fā)送消息
      PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
      printWriter.write(str + "\r\n");
      printWriter.flush();

      //關(guān)閉資源
      bufferedReader.close();
      printWriter.close();
      socket.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

Socket兩個參數(shù)分別是IP地址和端口號,可以通過以下代碼獲取IP地址:

   InetAddress ia = null;
   try {
     ia = ia.getLocalHost();
     String localname = ia.getHostName();
     String localip = ia.getHostAddress();
     System.out.println("本機名稱是:" + localname);
     System.out.println("本機的ip是 :" + localip);
   } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }

注意:關(guān)閉多余的網(wǎng)絡(luò)適配,只保留當前的網(wǎng)絡(luò)連接。關(guān)閉防火墻,安全軟件。不然可能導(dǎo)致連接不上。

ServerSocket服務(wù)端:

    try {
      mServerSocket = new java.net.ServerSocket(30004);

      Socket socket = mServerSocket.accept();

      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

      String content = null;
      while ((content=bufferedReader.readLine() )!= null) {
        System.out.println("接收到客服端發(fā)來的消息:" +content);
      }

      //關(guān)閉連接
      bufferedReader.close();
      socket.close();

    } catch (IOException e) {
      e.printStackTrace();
    }

服務(wù)端和客服端的端口號必須保持一致。下面我們運行兩個 java 程序看看效果:

android Socket實現(xiàn)簡單聊天功能以及文件傳輸

可能有些童鞋還不知道,怎么在AndroidStudio下面運行java程序,請看下面截圖:

android Socket實現(xiàn)簡單聊天功能以及文件傳輸

傳輸文件

Socket只能通過流去讀取消息,傳輸文件需要解決文章開始提出的問題, 如何判斷socket接收的數(shù)據(jù)是字符串還是流?

定義協(xié)議

為了保證接收到的數(shù)據(jù)類型統(tǒng)一(數(shù)據(jù)是字符串還是流),需要定義協(xié)議。定義協(xié)議的方式有很多種:

  • 發(fā)送一個握手信號。 根據(jù)握手信號來確定發(fā)送的是字符串還是流
  • 定義了Header(頭)和Body(實體),頭是固定大小的,用來告訴接收者數(shù)據(jù)的格式、用途、長度等信息,接收者根據(jù)Header來接受Body。
  • 自定義協(xié)議

我這里采用的自定義協(xié)議,原理跟前面兩種類似。我傳輸?shù)氖荍SON數(shù)據(jù),根據(jù)字段標識傳輸?shù)氖亲址€是流,接收者根據(jù)標識去解析數(shù)據(jù)即可。

協(xié)議的實體類(Transmission):

  //文件名稱
  public String fileName;

  //文件長度
  public long fileLength;

  //傳輸類型
  public int transmissionType;

  //傳輸內(nèi)容
  public String content;

  //傳輸?shù)拈L度
  public long transLength;

  //發(fā)送還是接受類型  1發(fā)送 2接收
  public int itemType = 1;

  //0 文本 1 圖片
  public int showType;

根據(jù)字段transmissionType去標識傳輸(序列化)或接收(反序列化)的類型。傳輸?shù)倪^程中始終都是以JSON的格式存在的。傳輸文件時需要把流轉(zhuǎn)換成字符串(方式很多種我用的是Base64加密與解密)。

客戶端(ClientThread)

客戶端發(fā)送文件的代碼如下:

  /**
   * 文件路徑
   *
   * @param filePath
   */
  private void sendFile(String filePath) {
    FileInputStream fis = null;
    File file = new File(filePath);

    try {
      mSendHandler.sendEmptyMessage(Constants.PROGRESS);

      fis = new FileInputStream(file);

      Transmission trans = new Transmission();
      trans.transmissionType = Constants.TRANSFER_FILE;
      trans.fileName = file.getName();
      trans.fileLength = file.length();
      trans.transLength = 0;

      byte[] bytes = new byte[1024];
      int length = 0;
      while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
        trans.transLength += length;
        trans.content = Base64Utils.encode(bytes);
        mPrintWriter.write(mGson.toJson(trans) + "\r\n");
        mPrintWriter.flush();

        //更新進度
        Message message = new Message();
        message.what = Constants.PROGRESS;
        message.obj = 100 * trans.transLength / trans.fileLength;
        mSendHandler.sendMessage(message);
      }
      fis.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      if (fis != null) {
        try {
          fis.close();
        } catch (IOException e1) {
          e1.printStackTrace();
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
      mPrintWriter.close();
    }
  }

文章結(jié)尾處我會附上源碼。

    trans.content = Base64Utils.encode(bytes);
    mPrintWriter.write(mGson.toJson(trans) + "\r\n");
    mPrintWriter.flush();

把字節(jié)流轉(zhuǎn)換成字符串傳輸Base64Utils.encode(bytes),接收方把字符串解析成字節(jié)流并寫入文件。

注意:在Android程序中運行,記得添加網(wǎng)絡(luò)文件讀寫的權(quán)限。

服務(wù)端(ServerThread)

服務(wù)端接收文件的代碼如下:

    long fileLength = trans.fileLength;
    long transLength = trans.transLength;
    if (mCreateFile) {
      mCreateFile = false;
      fos = new FileOutputStream(new File("d:/" + trans.fileName));
    }
    byte[] b = Base64Utils.decode(trans.content.getBytes());
    fos.write(b, 0, b.length);
    System.out.println("接收文件進度" + 100 * transLength / fileLength + "%...");
    if (transLength == fileLength) {
      mCreateFile = true;
      fos.flush();
      fos.close();
    }

服務(wù)端接收到文件,并存儲到了d盤。注意文件傳輸結(jié)束后關(guān)閉流。

源碼地址:SocketDemo_jb51.rar

下載源碼后,請先替換Constants類中HOST地址,然后運行MyServer的java程序,最后運行MainActivity的Android程序。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

新聞名稱:androidSocket實現(xiàn)簡單聊天功能以及文件傳輸
標題路徑:http://chinadenli.net/article44/jeiphe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、網(wǎng)站策劃、網(wǎng)站營銷、企業(yè)建站、網(wǎng)站設(shè)計、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管
婷婷伊人综合中文字幕| 精品熟女少妇一区二区三区| 日韩精品人妻少妇一区二区| 亚洲中文字幕在线观看四区| 亚洲精品黄色片中文字幕| 开心五月激情综合婷婷色| 亚洲av又爽又色又色| 国产小青蛙全集免费看| 国产成人综合亚洲欧美日韩| 国产日韩欧美国产欧美日韩| 亚洲伦片免费偷拍一区| 高清国产日韩欧美熟女| 亚洲av在线视频一区| 99福利一区二区视频| 清纯少妇被捅到高潮免费观看| 色婷婷丁香激情五月天| 搡老妇女老熟女一区二区| 国产精品免费自拍视频| 国产中文字幕一二三区| 91欧美一区二区三区| 亚洲清纯一区二区三区| 中日韩免费一区二区三区| 日韩专区欧美中文字幕| 尹人大香蕉中文在线播放| 日韩人妻欧美一区二区久久| 日本欧美一区二区三区高清| 色丁香之五月婷婷开心| 亚洲国产成人av毛片国产| 中国黄色色片色哟哟哟哟哟哟| 欧美一级日韩中文字幕| 日本免费一区二区三女| 欧美色欧美亚洲日在线| 污污黄黄的成年亚洲毛片| 激情三级在线观看视频| 亚洲精品成人福利在线| 日本不卡视频在线观看| 日韩精品福利在线观看| 欧美日韩校园春色激情偷拍 | 久久精品偷拍视频观看| 日韩特级黄片免费在线观看| 久久少妇诱惑免费视频|