• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.jme3.network.kernel.tcp;
34 
35 import com.jme3.network.kernel.Connector;
36 import com.jme3.network.kernel.ConnectorException;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.io.OutputStream;
40 import java.net.InetAddress;
41 import java.net.Socket;
42 import java.net.SocketAddress;
43 import java.nio.ByteBuffer;
44 import java.util.concurrent.atomic.AtomicBoolean;
45 
46 
47 /**
48  *  A straight forward socket-based connector implementation that
49  *  does not use any separate threading.  It relies completely on
50  *  the buffering in the OS network layer.
51  *
52  *  @version   $Revision: 8843 $
53  *  @author    Paul Speed
54  */
55 public class SocketConnector implements Connector
56 {
57     private Socket sock;
58     private InputStream in;
59     private OutputStream out;
60     private SocketAddress remoteAddress;
61     private byte[] buffer = new byte[65535];
62     private AtomicBoolean connected = new AtomicBoolean(false);
63 
SocketConnector( InetAddress address, int port )64     public SocketConnector( InetAddress address, int port ) throws IOException
65     {
66         this.sock = new Socket(address, port);
67         remoteAddress = sock.getRemoteSocketAddress(); // for info purposes
68 
69         // Disable Nagle's buffering so data goes out when we
70         // put it there.
71         sock.setTcpNoDelay(true);
72 
73         in = sock.getInputStream();
74         out = sock.getOutputStream();
75 
76         connected.set(true);
77     }
78 
checkClosed()79     protected void checkClosed()
80     {
81         if( sock == null )
82             throw new ConnectorException( "Connection is closed:" + remoteAddress );
83     }
84 
isConnected()85     public boolean isConnected()
86     {
87         if( sock == null )
88             return false;
89         return sock.isConnected();
90     }
91 
close()92     public void close()
93     {
94         checkClosed();
95         try {
96             Socket temp = sock;
97             sock = null;
98             connected.set(false);
99             temp.close();
100         } catch( IOException e ) {
101             throw new ConnectorException( "Error closing socket for:" + remoteAddress, e );
102         }
103     }
104 
available()105     public boolean available()
106     {
107         checkClosed();
108         try {
109             return in.available() > 0;
110         } catch( IOException e ) {
111             throw new ConnectorException( "Error retrieving data availability for:" + remoteAddress, e );
112         }
113     }
114 
read()115     public ByteBuffer read()
116     {
117         checkClosed();
118 
119         try {
120             // Read what we can
121             int count = in.read(buffer);
122             if( count < 0 ) {
123                 // Socket is closed
124                 close();
125                 return null;
126             }
127 
128             // Wrap it in a ByteBuffer for the caller
129             return ByteBuffer.wrap( buffer, 0, count );
130         } catch( IOException e ) {
131             if( !connected.get() ) {
132                 // Nothing to see here... just move along
133                 return null;
134             }
135             throw new ConnectorException( "Error reading from connection to:" + remoteAddress, e );
136         }
137     }
138 
write( ByteBuffer data )139     public void write( ByteBuffer data )
140     {
141         checkClosed();
142 
143         try {
144             out.write(data.array(), data.position(), data.remaining());
145         } catch( IOException e ) {
146             throw new ConnectorException( "Error writing to connection:" + remoteAddress, e );
147         }
148     }
149 
150 }
151