91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何利用NIO建立Socket服務器

發布時間:2021-07-21 21:06:58 來源:億速云 閱讀:151 作者:chen 欄目:編程語言

本篇內容介紹了“如何利用NIO建立Socket服務器”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

傳統的Java 的IO,利用Socket建立服務器,接收客戶端連接,一般都是為每一個連接建立一個線程,如果連接數巨大,那么服務器開銷也將巨大。。NIO的原理,可以參照圖:

如何利用NIO建立Socket服務器

Socket的Channel在Selector上注冊某一種動作,Selector通過select操作,監視所有在該Selector注冊過的Channel的對應的動作,如果監測到某一對應的動作,則返回selectedKeys,自己手動取到各個SelectionKey進行相應的處理。當然NIO不僅可以接受Socket的Channel,還有文件操作等其他IO操作。

作業的要求:

使用socket編程實現一個簡單的文件服務器。客戶端程序實現put功能(將一個文件從本地傳到文件服務器)和get功能(從文件服務器取一遠程文件存為本地文件)。客戶端和文件服務器不在同一臺機器上。

put [-h hostname] [-p portname] local_filename remote_filename
get [-h hostname] [-p portname] remote_filename local_filename

服務器端不使用nio,直接使用io的socket代碼如下:

import java.io.*; import java.net.ServerSocket; import java.net.Socket;  public class ServerMain {          public static void main(String[] args) {          class SocketThread extends Thread{                          private Socket socket;             private byte[] buf;             private int len = 0;             public SocketThread(Socket socket) {                  this.socket = socket;                 buf = new byte[1024];             }              @Override             public void run() {                 try {                        DataInputStream dis = new DataInputStream(socket.getInputStream());                     DataOutputStream dos = new DataOutputStream(socket.getOutputStream());                                           //String command = dis.readUTF();                      len = dis.read(buf);                     String command = new String(buf,0,len);                                          System.out.println("command=="+command);                                          String[] temp =command.split(" ");                     command = temp[0];  //命令  是put還是get                     String filename = temp[1];  //文件名                                          File file = new File("C:\\",filename);//假設放在C盤                     if(command.equals("get")){                         if(!file.exists()){                             //dos.writeUTF("notexists");                             dos.write("notexists".getBytes());                             dos.flush();                             System.out.println("沒有這個文件,無法提供下載!");                             dis.close();                             dos.close();                             socket.close();                             return;                         }                         //dos.writeUTF("DownloadReady "+file.length());                          dos.write("準備下載".getBytes());                         dos.flush();                                                  System.out.println("正在接受文件下載...");                         DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));                             while ((len = fis.read(buf))!= -1) {                              dos.write(buf, 0, len);                         }                         dos.flush();                                                  fis.close();                              System.out.println("文件傳輸完成");                     }                     else {                          //dos.writeUTF("UploadReady");                          dos.write("UploadReady".getBytes());                         dos.flush();                                                  System.out.println("正在接受文件上傳...");                         DataOutputStream fileOut =                              new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));                           while ((len = dis.read(buf))!=-1) {                                fileOut.write(buf, 0, len);                         }                         System.out.println("上傳完畢!");                         fileOut.close();                      }                     dis.close();                     dos.close();                     socket.close();                  } catch (Exception e) {                     e.printStackTrace();                 }             }                      }                  System.out.println("等待客戶端連接....");         int index = 0;         try {             ServerSocket server = new ServerSocket(9527,300); //端口號9527  允許***連接數300             while (true) {                 Socket socket = server.accept();                 System.out.println("收到第"+(++index)+"個連接");                 new SocketThread(socket).start(); //對每個連接創建一個線程             }         } catch (Exception e) {             e.printStackTrace();         }     } }

使用NIO建立的Socket服務器,代碼如下:

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer;  import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.util.Iterator;  public class NewSocketServer {       private static final int port = 9527;     private Selector selector;     private ByteBuffer clientBuffer = ByteBuffer.allocate(1024);       private CharsetDecoder decoder = Charset.forName("GB2312").newDecoder();     private CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();      //編碼解碼格式設置成GBK也行.UTF-8不行,中文亂碼  (前提都是客戶端沒有設置任何編碼解碼格式)          public void setListener() throws Exception{                  selector = Selector.open(); //打開選擇器                     ServerSocketChannel server = ServerSocketChannel.open();  //定義一個 ServerSocketChannel通道         server.socket().bind(new InetSocketAddress(port));  //ServerSocketChannel綁定端口           server.configureBlocking(false);   //配置通道使用非阻塞模式         server.register(selector, SelectionKey.OP_ACCEPT); //該通道在selector上注冊  接受連接的動作                  while(true)         {                 selector.select();   //select() 會阻塞,直到在該selector上注冊的channel有對應的消息讀入             Iterator iter = selector.selectedKeys().iterator();                while (iter.hasNext()) {                     SelectionKey key = (SelectionKey) iter.next();                    iter.remove();  // 刪除此消息                  process(key);   // 當前線程內處理。(為了高效,一般會在另一個線程中處理此消息)             }            }        }           private void process(SelectionKey key) throws IOException {                if (key.isAcceptable()) { // 接收請求                    ServerSocketChannel server = (ServerSocketChannel) key.channel();                    SocketChannel channel = server.accept();//類似于io的socket,ServerSocketChannel的accept函數返回 SocketChannel                 channel.configureBlocking(false);   //設置非阻塞模式                    SelectionKey sKey = channel.register(selector, SelectionKey.OP_READ);                  sKey.attach("read_command"); //這兒接收到連接請求之后可以為每個連接設置一個ID             }              else if (key.isReadable()) { // 讀信息                     SocketChannel channel = (SocketChannel) key.channel();                    String name = (String) key.attachment();                  if(name.equals("read_command")){                     int count = channel.read(clientBuffer);                      if (count > 0) {                            clientBuffer.flip();                            CharBuffer charBuffer = decoder.decode(clientBuffer);                            String command = charBuffer.toString();                                                     //command形如:get abc.png 或者  put aaa.png                         System.out.println("command===="+command);  //得到客戶端傳來的命令                                                   String[] temp =command.split(" ");                         command = temp[0];  //命令  是put還是get                         String filename = temp[1];  //文件名                                                  SelectionKey sKey = channel.register(selector,SelectionKey.OP_WRITE);                            if(command.equals("put"))sKey.attach("UploadReady#"+filename);  //要保護該通道的文件名                         else if(command.equals("get")){                              if(!new File("C:\\",filename).exists()){ //假設文件都是在C盤根目錄                                 System.out.println("沒有這個文件,無法提供下載!");                                 sKey.attach("notexists");                              }                             else sKey.attach("DownloadReady#"+filename); //要保護該通道的文件名                         }                     } else {                            channel.close();                        }                    }                 else if(name.startsWith("read_file")){//這兒可以新開一個線程     文件操作也可以用NIO                      DataOutputStream fileOut =                          new DataOutputStream(                                 new BufferedOutputStream(                                         new FileOutputStream(                                                 new File("C:\\",name.split("#")[1]))));                       int passlen = channel.read(clientBuffer);                       while (passlen>=0) {                            clientBuffer.flip();                           fileOut.write(clientBuffer.array(), 0, passlen);                          passlen = channel.read(clientBuffer);                     }                     System.out.println("上傳完畢!");                     fileOut.close();                      channel.close();                 }                 clientBuffer.clear();                }              else if (key.isWritable()) { // 寫事件                    SocketChannel channel = (SocketChannel) key.channel();                    String flag = (String) key.attachment();                     if(flag.startsWith("downloading")){//這兒可以新開一個線程   文件操作也可以用NIO                     DataInputStream fis = new DataInputStream(                             new BufferedInputStream(                                     new FileInputStream(                                             new File("C:\\",flag.split("#")[1]))));                                            byte[] buf = new byte[1024];                     int len =0;                      while ((len = fis.read(buf))!= -1) {                          channel.write(ByteBuffer.wrap(buf, 0, len));                       }                       fis.close();                          System.out.println("文件傳輸完成");                     channel.close();                 }                 else if(flag.equals("notexists")){                      //channel.write(encoder.encode(CharBuffer.wrap(flag)));                        channel.write(ByteBuffer.wrap(flag.getBytes())); //不用編碼也行    客戶端直接接收    中文也不是亂碼                     channel.close();                 }                 else if(flag.startsWith("UploadReady")){                      channel.write(encoder.encode(CharBuffer.wrap("UploadReady")));                                           //這兒如果不重新注冊該通道的讀操作    selector選擇到該通道的將繼續永遠是寫操作,也就無法跳轉到上面的接受上傳的處理                     SelectionKey sKey =channel.register(selector, SelectionKey.OP_READ);//register是覆蓋的????!!!                     sKey.attach("read_file#"+flag.split("#")[1]);                     //key.attach("read_file#"+flag.split("#")[1]); //select不到讀操作                 }                 else if(flag.startsWith("DownloadReady")){                      channel.write(ByteBuffer.wrap("準備下載".getBytes()));                      //channel.write(encoder.encode(CharBuffer.wrap("準備下載")));                        key.attach("downloading#"+flag.split("#")[1]);                 }              }           }             public static void main(String[] args) {                  try {              System.out.println("等待來至" + port + "端口的客戶端連接.....");              new NewSocketServer().setListener();         } catch (Exception e) {             e.printStackTrace();         }      } }

客戶端代碼如下:

import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.util.Scanner;  public class ClientMain {      private   int ServerPort = 9527;     private   String ServerAddress = "192.168.1.154";     private   String GetOrPut = "get";        private   String local_filename = "";      private   String remote_filename  = "";      private   byte[] buf;     private   int len;     class SocketThread extends Thread{                  @Override         public void run() {              try {                                  File file = new File("C:\\",local_filename); //假設文件放在C盤                 if(!file.exists()&&GetOrPut.equals("put")){                      System.out.println("本地沒有這個文件,無法上傳!");                      return;                 }                                   InetAddress loalhost = InetAddress.getLocalHost();                 Socket socket = new Socket(ServerAddress,ServerPort,loalhost,44);                                             //服務器IP地址  端口號   本機IP 本機端口號                 DataInputStream dis = new DataInputStream(socket.getInputStream());                 DataOutputStream dos = new DataOutputStream(socket.getOutputStream());                                   //dos.writeUTF(GetOrPut+" "+remote_filename);//服務器端如果是io的socket,writeUTF和writeUTF對接                 dos.write((GetOrPut+" "+remote_filename).getBytes());                 dos.flush();                                 //String tempString = dis.writeUTF();                  buf = new byte[1024];                 len = dis.read(buf);                 String tempString = new String(buf,0,len);//服務器反饋的信息                                  //System.out.println(tempString);                  if(tempString.equals("notexists")){                     System.out.println("服務器沒有這個文件,無法下載!");                      dos.close();                     dis.close();                     socket.close();                     return;                 }                                  if(tempString.startsWith("準備下載")){                       DataOutputStream fileOut =                          new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));                       while ((len = dis.read(buf))!=-1) {                            fileOut.write(buf, 0, len);                     }                     System.out.println("下載完畢!");                     fileOut.close();                     dos.close();                     dis.close();                     socket.close();                 }                 else if(tempString.equals("UploadReady")){                       System.out.println("正在上傳文件.......");                     DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));                                             while ((len = fis.read(buf))!= -1) {                           dos.write(buf, 0, len);                     }                     dos.flush();                     System.out.println("上傳完畢!");                     fis.close();                     dis.close();                     dos.close();                     socket.close();                 }                              } catch (Exception e) {                 e.printStackTrace();             }         }              }          public boolean checkCommand(String command)     {          if(!command.startsWith("put")&&!command.startsWith("get")){             System.out.println("輸入命令錯誤");             return false;         }                  int index = -1;         String temp = "";         String[] tempStrings = null;                  if((index=command.indexOf("-h"))>0){             temp = command.substring(index+3);             temp = temp.substring(0, temp.indexOf(' '));             ServerAddress = temp;         }         if((index=command.indexOf("-p"))>0){             temp = command.substring(index+3);             temp = temp.substring(0, temp.indexOf(' '));             ServerPort = Integer.valueOf(temp);         }                  tempStrings = command.split(" ");         if(command.startsWith("put")){             GetOrPut = "put";             local_filename = tempStrings[tempStrings.length-2];             remote_filename = tempStrings[tempStrings.length-1];         }         else if(command.startsWith("get")){             GetOrPut = "get";             local_filename = tempStrings[tempStrings.length-1];             remote_filename = tempStrings[tempStrings.length-2];         }                  return true;     }          public static void main(String[] args) {         ClientMain thisC= new ClientMain();          Scanner sc = new Scanner(System.in);         String commandString = "";         do {             System.out.println("請輸入命令:");              commandString = sc.nextLine();         } while (!thisC.checkCommand(commandString));                   ClientMain.SocketThread a = thisC.new SocketThread();         a.start();     } }

“如何利用NIO建立Socket服務器”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

nio
AI

安达市| 防城港市| 永吉县| 麻城市| 黑龙江省| 高碑店市| 仁寿县| 天台县| 蒲城县| 望江县| 宾川县| 九台市| 汝南县| 汽车| 仙居县| 那坡县| 临沧市| 定兴县| 凌云县| 合江县| 佛坪县| 泊头市| 女性| 清徐县| 贡嘎县| 广汉市| 沂源县| 辽阳市| 宜兰县| 河西区| 客服| 六盘水市| 巩义市| 无极县| 桓台县| 葵青区| 饶河县| 英德市| 彰化县| 满城县| 闽清县|