Java uses NIO to establish a Socket server
The Socket Channel registers an action on the Selector. The Selector uses the select action to monitor the actions of all the channels registered with the Selector. If a corresponding action is detected, the return value is selectedKeys, and each SelectionKey is obtained manually for processing. Of course, NIO can not only accept Socket channels, but also file operations and other IO operations.
AD: WOT2015 Internet O & M and Developer Conference selling tickets
Traditional Java IO uses Socket to establish a server and receive client connections. Generally, a thread is created for each connection. If the number of connections is large, the server overhead will also be huge .. The following figure shows the NIO principle:
The Socket Channel registers an action on the Selector. The Selector uses the select action to monitor the actions of all the channels registered with the Selector. If a corresponding action is detected, the return value is selectedKeys, and each SelectionKey is obtained manually for processing. Of course, NIO can not only accept Socket channels, but also file operations and other IO operations.
Job Requirements:
Use socket programming to implement a simple file server. The client program implements the put function (transferring a file from the local to the file server) and get function (saving a remote file as a local file from the file server ). The client and the file server are not on the same machine.
put [-h hostname] [-p portname] local_filename remote_filenameget [-h hostname] [-p portname] remote_filename local_filename
The server does not use nio. The socket code for using io directly is as follows:
- 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]; // whether the command is put or get
- String filename = temp [1]; // file name
-
- File file = new File ("C: \", filename); // assume that the File is on drive C.
- If (command. equals ("get ")){
- If (! File. exists ()){
- // Dos. writeUTF ("notexists ");
- Dos. write ("notexists". getBytes ());
- Dos. flush ();
- System. out. println ("this file is not available and cannot be downloaded! ");
- Dis. close ();
- Dos. close ();
- Socket. close ();
- Return;
- }
- // Dos. writeUTF ("DownloadReady" + file. length ());
- Dos. write ("prepare to download". getBytes ());
- Dos. flush ();
-
- System. out. println ("the file is being downloaded ...");
- DataInputStream FD = new DataInputStream (new BufferedInputStream (new FileInputStream (file )));
-
- While (len = FS. read (buf ))! =-1 ){
- Dos. write (buf, 0, len );
- }
- Dos. flush ();
-
- FCM. close ();
- System. out. println ("file transfer completed ");
- }
- Else {
- // Dos. writeUTF ("UploadReady ");
- Dos. write ("UploadReady". getBytes ());
- Dos. flush ();
-
- System. out. println ("accepting file upload ...");
- DataOutputStream fileOut =
- New DataOutputStream (new BufferedOutputStream (new FileOutputStream (file )));
-
- While (len = dis. read (buf ))! =-1 ){
- FileOut. write (buf, 0, len );
- }
- System. out. println ("uploaded! ");
- FileOut. close ();
- }
- Dis. close ();
- Dos. close ();
- Socket. close ();
- } Catch (Exception e ){
- E. printStackTrace ();
- }
- }
-
- }
-
- System. out. println ("waiting for client connection ....");
- Int index = 0;
- Try {
- ServerSocket server = new ServerSocket (9527,300); // port number 9527 maximum number of connections allowed 300
- While (true ){
- Socket socket = server. accept ();
- System. out. println ("received" + (++ index) + "connection ");
- New SocketThread (socket). start (); // create a thread for each connection
- }
- } Catch (Exception e ){
- E. printStackTrace ();
- }
- }
- }
The code for using the Socket server established by NIO is as follows:
- 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 ();
- // Encoding and decoding format is set to GBK also line. UTF-8 is not good, Chinese garbled (the premise is that the client did not set any encoding and decoding format)
-
- Public void setListener () throws Exception {
-
- Selector = Selector. open (); // open the selector
-
- ServerSocketChannel server = ServerSocketChannel. open (); // defines a ServerSocketChannel
- Server. socket (). bind (new InetSocketAddress (port); // ServerSocketChannel binding port
- Server. configureBlocking (false); // configure the channel to use the non-blocking mode
- Server. register (selector, SelectionKey. OP_ACCEPT); // This channel registers the action of accepting connections on the selector.
-
- While (true)
- {
- Selector. select (); // select () will be blocked until the channel registered on the selector has the corresponding message read
- Iterator iter = selector. selectedKeys (). iterator ();
- While (iter. hasNext ()){
- SelectionKey key = (SelectionKey) iter. next ();
- Iter. remove (); // Delete the message
- Process (key); // process in the current thread. (For efficiency, this message is generally processed in another thread)
- }
- }
- }
-
- Private void process (SelectionKey key) throws IOException {
- If (key. isAcceptable () {// receives the request
- ServerSocketChannel server = (ServerSocketChannel) key. channel ();
- SocketChannel channel = server. accept (); // similar to the socket of io, the accept function of ServerSocketChannel returns SocketChannel
- Channel. configureBlocking (false); // sets the non-blocking mode.
- SelectionKey sKey = channel. register (selector, SelectionKey. OP_READ );
- SKey. attach ("read_command"); // After receiving the connection request, you can set an ID for each connection.
- }
- Else if (key. isReadable () {// read information
- 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 Format: get abc.png or put aaa.png
- System. out. println ("command =" + command); // obtain the command from the client.
-
- String [] temp = command. split ("");
- Command = temp [0]; // whether the command is put or get
- String filename = temp [1]; // file name
-
- SelectionKey sKey = channel. register (selector, SelectionKey. OP_WRITE );
- If (command. equals ("put") sKey. attach ("UploadReady #" + filename); // File Name of the channel to be protected
- Else if (command. equals ("get ")){
- If (! New File ("C :\\", filename). exists () {// assume that all files are in the C root directory.
- System. out. println ("this file is not available and cannot be downloaded! ");
- SKey. attach ("notexists ");
- }
- Else sKey. attach ("DownloadReady #" + filename); // File Name of the channel to be protected
- }
- } Else {
- Channel. close ();
- }
- }
- Else if (name. startsWith ("read_file") {// you can open a new thread file or use 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 ("uploaded! ");
- FileOut. close ();
- Channel. close ();
- }
- ClientBuffer. clear ();
- }
- Else if (key. isWritable () {// write event
- SocketChannel channel = (SocketChannel) key. channel ();
- String flag = (String) key. attachment ();
- If (flag. startsWith ("downloading") {// you can open a new thread file or use NIO
- DataInputStream FD = new DataInputStream (
- New BufferedInputStream (
- New FileInputStream (
- New File ("C :\\", flag. split ("#") [1]);
-
- Byte [] buf = new byte [1, 1024];
- Int len = 0;
- While (len = FS. read (buf ))! =-1 ){
- Channel. write (ByteBuffer. wrap (buf, 0, len ));
- }
- FCM. close ();
- System. out. println ("file transfer completed ");
- Channel. close ();
- }
- Else if (flag. equals ("notexists ")){
- // Channel. write (encoder. encode (CharBuffer. wrap (flag )));
- Channel. write (ByteBuffer. wrap (flag. getBytes (); // The client can directly receive Chinese characters without encoding or garbled characters.
- Channel. close ();
- }
- Else if (flag. startsWith ("UploadReady ")){
- Channel. write (encoder. encode (CharBuffer. wrap ("UploadReady ")));
-
- // If you do not re-register the read operation selector of this channel and select this channel, it will always be a write operation, and you will not be able to jump to the above process for receiving uploads.
- SelectionKey sKey = channel. register (selector, SelectionKey. OP_READ); // register is overwritten ????!!!
- SKey. attach ("read_file #" + flag. split ("#") [1]);
- // Key. attach ("read_file #" + flag. split ("#") [1]); // select cannot read
- }
- Else if (flag. startsWith ("DownloadReady ")){
- Channel. write (ByteBuffer. wrap ("prepare to download". getBytes ()));
- // Channel. write (encoder. encode (CharBuffer. wrap ("prepare to download ")));
- Key. attach ("downloading #" + flag. split ("#") [1]);
- }
- }
- }
-
- Public static void main (String [] args ){
-
- Try {
- System. out. println ("waiting for" + port + "port client connection .....");
- New NewSocketServer (). setListener ();
- } Catch (Exception e ){
- E. printStackTrace ();
- }
-
- }
- }
The client code is as follows:
- Import java. io .*;
- Import java.net. InetAddress;
- Import java.net. Socket;
- Import java. util. collections;
-
- 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); // assume that the File is placed on drive C.
- If (! File. exists () & GetOrPut. equals ("put ")){
- System. out. println ("this file does not exist locally and cannot be uploaded! ");
- Return;
- }
-
- InetAddress loalhost = InetAddress. getLocalHost ();
- Socket socket = new Socket (ServerAddress, ServerPort, loalhost, 44 );
- // Server IP address port number local IP local port number
- DataInputStream dis = new DataInputStream (socket. getInputStream ());
- DataOutputStream dos = new DataOutputStream (socket. getOutputStream ());
-
- // Dos. writeUTF (GetOrPut + "" + remote_filename); // connection between writeUTF and writeUTF on the server side if it is an io socket
- 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); // server feedback
-
- // System. out. println (tempString );
- If (tempString. equals ("notexists ")){
- System. out. println ("the server does not have this file and cannot download it! ");
- Dos. close ();
- Dis. close ();
- Socket. close ();
- Return;
- }
-
- If (tempString. startsWith ("prepare to download ")){
- DataOutputStream fileOut =
- New DataOutputStream (new BufferedOutputStream (new FileOutputStream (file )));
-
- While (len = dis. read (buf ))! =-1 ){
- FileOut. write (buf, 0, len );
- }
- System. out. println ("download completed! ");
- FileOut. close ();
- Dos. close ();
- Dis. close ();
- Socket. close ();
- }
- Else if (tempString. equals ("UploadReady ")){
- System. out. println ("uploading file .......");
- DataInputStream FD = new DataInputStream (new BufferedInputStream (new FileInputStream (file )));
-
- While (len = FS. read (buf ))! =-1 ){
- Dos. write (buf, 0, len );
- }
- Dos. flush ();
- System. out. println ("uploaded! ");
- FCM. 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 ("input command error ");
- 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 ();
- Pipeline SC = new pipeline (System. in );
- String commandString = "";
- Do {
- System. out. println ("Enter the command :");
- CommandString = SC. nextLine ();
- } While (! ThisC. checkCommand (commandString ));
-
- ClientMain. SocketThread a = thisC. new SocketThread ();
- A. start ();
- }
- }