Non-blocking Server/Client is blocking...?!
First, a simple question:
Why in most example code using Selectors, when iterating over the Set returned by Selector.selectedKeys() does the currently selected SelectionKey get removed from the Iterator? I see it all the time, but since the SelectionKey is still bound to the underlying Selector it seems to not really do anything.
Now to my main problem:
I been working with 1.4 for a week now trying to implement a simple test server/client, whereby the server constantly sends out the current time to any subscribing clients, who in turn display the time to stdout. Pretty straight forward, huh?
Well, everything seems to go fine...once. The Server accepts the client connection, sends out a the current time, the client (only one for now) receives it, displays to the screen, but then both server and client block on the Selector.select() method.
If I shut down the client, the server then continues through the select() method, finding one SelectionKey, tries to write to it and throws an IOException (since the client is no more). I'm catching that exception and then removing the channel from the Selector, so that the server may continue to service requests.
When starting a second client while the first is still running causes the following sequence of events:
Server: starts up
ClientA: connects to server
Server: broadcasts the time
ClientA: displays time
// nothing else happens until...
ClientB: connects to server
Server: broadcasts the time
ClientA: displays time
ClientB: displays time
//everything blocks again...
ClientA: disconnects from server
Server: broadcasts the time
ClientB: displays time
As you can see it seems everything blocks until a client does something (connect/disconnect).
I will post code if anyone asks, but I don't want to spam the board if no one is willing to help me.
-Justin
You got it!
// ********** SERVER **********
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
public class TestServer
private static final int DEFAULT_PORT = 9999;
public static void main(String[] args)
TestServer s = new TestServer();
}//end of main(String[])
public TestServer()
this(DEFAULT_PORT);
}// end of TestServer()
public TestServer(int port)
InetSocketAddress addr = new InetSocketAddress(port);
try
Selector acceptSelector = Selector.open();
Selector broadcastSelector = Selector.open();
ConnectionList connections = new ConnectionList(broadcastSelector);
Acceptor a = new Acceptor(acceptSelector, addr, connections);
Broadcaster b = new Broadcaster(broadcastSelector, connections);
a.start();
b.start();
}// end of try
catch (Exception ex)
ex.printStackTrace();
}// end of catch
}// end of TestServer(int)
private static String status(Selector s)
StringBuffer sb = new StringBuffer(100);
sb.append("Selector: ");
Set keys = s.keys();
sb.append("\n\tNum Keys: ");
sb.append(keys.size());
Iterator iter = keys.iterator();
int i = 0;
while (iter.hasNext())
try
sb.append("\n\t[");
sb.append(i++);
sb.append("]:");
SelectionKey key = (SelectionKey)iter.next();
sb.append(" acceptable=");
sb.append(key.isAcceptable());
sb.append(" connectable=");
sb.append(key.isConnectable());
sb.append(" readable=");
sb.append(key.isReadable());
sb.append(" writable=");
sb.append(key.isWritable());
}// end of try
catch (CancelledKeyException cke)
sb.append("*** CANCELLED KEY");
}// end of catch
}// end of while
return sb.toString();
}// end of status(Selector)
class Broadcaster extends Thread
private final String TF = Broadcaster.class.getName();
private int BUFFER_SIZE = 2048;
private Selector selector_;
private ConnectionList connections_;
private ByteBuffer buffer_;
public Broadcaster(Selector selector, ConnectionList connections)
super("Broadcaster");
selector_ = selector;
connections_ = connections;
buffer_ = ByteBuffer.allocateDirect(BUFFER_SIZE);
public void run()
while (true)
try
registerNewChannels();
System.out.println("BroadcasterThread: Before select() "+status(selector_));
System.out.println("BroadcasterThread: Selecting...");
int keysReady = selector_.select();
System.out.println("BroadcasterThread: After select() "+status(selector_));
System.out.println("BroadcasterThread: "+keysReady+" ready Key(s)");
if (keysReady > 0)
transmit();
}// end of if
}// end of try
catch (Exception ex)
ex.printStackTrace();
return;
}// end of catch
}// end of while
protected void registerNewChannels()
throws Exception
SocketChannel channel = null;
while (null != (channel = connections_.removeFirst()))
channel.configureBlocking(false);
channel.register(selector_, SelectionKey.OP_WRITE);
System.out.println("BroadcasterThread: Registered connection from " + channel.socket().getInetAddress());
}// end of while
}// end of registerNewChannels()
public void transmit()
throws Exception
Set readyKeys = selector_.selectedKeys();
System.out.println("BroadcasterThread: Selected Keys: "+readyKeys.size());
SelectionKey tempKey = null;
SocketChannel tempChannel = null;
fillBuffer();
for (Iterator i = readyKeys.iterator(); i.hasNext(); )
tempKey = (SelectionKey)i.next();
tempChannel = (SocketChannel)tempKey.channel();
if (tempKey.isWritable())
System.out.println("BroadcasterThread: Key selected is Writable");
try
tempChannel.write(buffer_);
System.out.println("BroadcasterThread: Sent message to "+tempChannel.socket().getInetAddress());
}// end of try
catch (IOException ioe)
System.err.println("BroadcasterThread: Lost Connection");
tempChannel.close();
}// end of catch
}// end of if
else
System.out.println("BroadcasterThread: Key selected is not Writable");
}// end of else
}// end of for
buffer_.clear();
}// end of transmit()
private void fillBuffer()
buffer_.clear();
/* Place Date in Buffer */
long time = System.currentTimeMillis();
Date d = new Date(time);
System.out.println("BroadcasterThread: Broadcasting "+d);
String date = d.toString()+"\n";
byte[] datebuff = date.getBytes();
buffer_.put(datebuff);
/* Prepare for read operations */
buffer_.flip();
}// end of fillBuffer()
}//end of inner class Broadcaster
class Acceptor extends Thread
private Selector selector_;
private ConnectionList connList_;
private final String TF = Acceptor.class.getName();
public Acceptor(Selector selector, InetSocketAddress address, ConnectionList connList)
super("Acceptor");
selector_ = selector;
connList_ = connList;
try
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(address);
System.out.println("AcceptorThread: Bound to " + address);
ssc.register(selector_, SelectionKey.OP_ACCEPT);
}// end of try
catch (Exception ex)
ex.printStackTrace();
}// end of catch
public void run()
while (true)
try
System.out.println("AcceptorThread: Selecting...");
int keysReady = selector_.select();// block till a channel is ready
System.out.println("AcceptorThread: "+keysReady+" Keys Ready");
if (keysReady > 0)
acceptPendingConnections();
}// end of if
catch (Exception ex)
ex.printStackTrace();
protected void acceptPendingConnections()
throws Exception
Set readyKeys = selector_.selectedKeys();
System.out.println("AcceptorThread: Selected "+readyKeys.size()+" Keys");
for (Iterator i = readyKeys.iterator(); i.hasNext(); )
SelectionKey key = (SelectionKey)i.next();
i.remove();
ServerSocketChannel readyChannel = (ServerSocketChannel)key.channel();
SocketChannel incomingChannel = readyChannel.accept();
System.out.println("AcceptorThread: Connection from " + incomingChannel.socket().getInetAddress());
connList_.add(incomingChannel);
}// end of for
}// end of acceptPendingConnections()
}// end of inner class Acceptor
class ConnectionList
private LinkedList list_;
private Selector selectorToNotify_;
public ConnectionList(Selector toNotify)
list_ = new LinkedList();
selectorToNotify_ = toNotify;
}// end of ConnectionList(Selector)
public synchronized void add(SocketChannel newlyConnectedChannel)
list_.add(newlyConnectedChannel);
selectorToNotify_.wakeup();
}// end of add(SocketChannel)
public synchronized SocketChannel removeFirst()
SocketChannel first = null;
if (list_.size() > 0)
first = (SocketChannel)list_.removeFirst();
}//end of if
return first;
}// end of removeFirst()
}// end of inner class ConnectionList
}// end of class TestServer
// ********** CLIENT **********
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Iterator;
import java.util.Set;
public class TestClient
public static final String TF = TestClient.class.getName();
private static final String DEFAULT_SERVER_IP = "127.0.0.1";
private static final int DEFAULT_SERVER_PORT = 9999;
private InetSocketAddress serverAddr_;
private Selector connectSelector_;
private Selector readSelector_;
private WritableByteChannel outputChannel_;
private ByteBuffer receiveBuffer_;
private SocketChannel serverChannel_;
public static void main(String[] args)
TestClient c = new TestClient();
}// end of main(String[])
public TestClient()
this(DEFAULT_SERVER_IP, DEFAULT_SERVER_PORT);
}// end of TestClient()
public TestClient(String ip, int port)
try
serverAddr_ = new InetSocketAddress(ip, port);
connectSelector_ = Selector.open();
readSelector_ = Selector.open();
outputChannel_ = Channels.newChannel(System.out);
receiveBuffer_ = ByteBuffer.allocateDirect(512);
connect();
run();
}// end of try
catch (Exception ex)
ex.printStackTrace();
}// end of catch
}// end of TestClient(String, int)
private void connect()
throws Exception
serverChannel_ = SocketChannel.open();
serverChannel_.configureBlocking(false);
serverChannel_.connect(serverAddr_);
serverChannel_.register(connectSelector_, SelectionKey.OP_CONNECT);
int numKeys = 0;
while (numKeys <= 0)
System.out.println("connect(): Selecting...");
numKeys = connectSelector_.select();
System.out.println("connect(): "+numKeys+" ready Key(s)");
Set readyKeys = connectSelector_.selectedKeys();
System.out.println("connect(): Selected Keys: "+readyKeys.size());
if (numKeys > 0)
SelectionKey tempKey = null;
SocketChannel tempChannel = null;
Iterator i = readyKeys.iterator();
while (i.hasNext())
tempKey = (SelectionKey)i.next();
i.remove();
tempChannel = (SocketChannel)tempKey.channel();
if (tempKey.isConnectable())
System.out.println("connect(): Key selected is Connectable");
if (tempChannel.isConnectionPending())
System.out.println("connect(): Connection Pending");
tempChannel.finishConnect();
System.out.println("connect(): Connection Completed");
}// end of if
}// end of if
else
System.out.println("connect(): Key selected is not Connectable");
}// end of else
}// end of while
}// end of if
}// end of while
}// end of connect()
private void run()
throws Exception
serverChannel_.register(readSelector_, SelectionKey.OP_READ);
while (true)
System.out.println("run(): Before select() "+status(readSelector_));
System.out.println("run(): Selecting...");
int numKeys = readSelector_.select();
System.out.println("run(): After select() "+status(readSelector_));
System.out.println("run(): "+numKeys+" Ready Key(s)");
if (numKeys > 0)
processKeys();
}// end of if
}// end of while
}// end of run()
private void processKeys()
throws Exception
Set readyKeys = readSelector_.selectedKeys();
System.out.println("processKeys(): Selected Keys: "+readyKeys.size());
SelectionKey tempKey = null;
SocketChannel tempChannel = null;
for (Iterator i = readyKeys.iterator(); i.hasNext(); )
tempKey = (SelectionKey)i.next();
tempChannel = (SocketChannel)tempKey.channel();
if (tempKey.isReadable())
System.out.println("processKeys(): Key selected is Readable");
try
tempChannel.read(receiveBuffer_);
receiveBuffer_.flip();
outputChannel_.write(receiveBuffer_);
receiveBuffer_.clear();
}// end of try
catch (IOException ioe)
System.out.println("processKeys(): Lost Connection");
tempKey.cancel();
}// end of catch
}// end of if
else
System.out.println("processKeys(): Key selected is not Readable");
}// end of else
}// end of for
}// end of processKeys()
private static String status(Selector s)
StringBuffer sb = new StringBuffer(100);
sb.append("Selector: ");
Set keys = s.keys();
sb.append("\n\tNum Keys: ");
sb.append(keys.size());
Iterator iter = keys.iterator();
int i = 0;
while (iter.hasNext())
try
sb.append("\n\t[");
sb.append(i++);
sb.append("]:");
SelectionKey key = (SelectionKey)iter.next();
sb.append(" acceptable=");
sb.append(key.isAcceptable());
sb.append(" connectable=");
sb.append(key.isConnectable());
sb.append(" readable=");
sb.append(key.isReadable());
sb.append(" writable=");
sb.append(key.isWritable());
}// end of try
catch (CancelledKeyException cke)
sb.append("*** CANCELLED KEY");
}// end of catch
}// end of while
return sb.toString();
}// end of status(Selector)
}// end of class TestClient
Similar Messages
-
Writing Java Non-Blocking Socket Server for Winsock Client
Hi.
Im a newbie to Sockets. I need to write a Non-Blocking Socket server (using java.nio) that accepts connection and reads the data sent by WinSock clients, and write them to another winsock client. Its quite intriguing. How do I do that? Is it possible?
Thanks in advance
ArunWell, in traditional 4.2 BSD sockets, you'd fill up a set of filedescriptors of connections (an array of bits usually), and push that in the read parameter of a call to 'select'. Select then blocks until at least one of the file descriptors become available for reading, or writing if you also made an fd_set full of file descriptors (but you can usually write freely to a socket, so there is not much use for that). Then you start finding out which of these file descriptors have actually become available for reading, and you pass those to a bunch of worker-threads. The advantage is that your set of worker-threads can be quite small, while your number of connections can still be quite large (unless, of course, everyone of your clients start talking all at once, but that is no different from the one-socket-one-thread-model that java.net.* forces upon you).
In java, the 'select' call is replaced by a call to java.nio.channels.Selector.select(); and then the fishing out of the selected stuff comes from java.nio.channels.Selector.selectedKeys().
To add a thingy to a selector, use (for example) java.nio.channel.ServerSocketChannel.register(Selector, ops, att);
whereby the ops parameter is the kind of action you'd like to select this channel for; SelectionKey.OP_READ etc..
The workerthread bit is also easy to write, but I leave that to you as an exercise. -
NIO Non-Blocking Server not Reading from Key
I have created a NIO non blocking server (below) and it will not pick up any input from the client.... My log doesnt even show that it enters the readKey() method, so it must be something before. Any help would be appreciated.
Scott
package jamb.server;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import jamb.server.client.Client;
public class Server {
private Selector selector;
private ServerSocketChannel serverChannel;
private static Logger logger = Logger.getLogger("jamb.server");
private static Preferences prefs = Preferences.systemRoot().node("/jamb/server");
public void init() {
logger.entering("jamb.server.Server", "init");
//Get a selector...
try {
selector = SelectorProvider.provider().openSelector();
//Open the SocketChannel and make it non-blocking...
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
//Bind the server to the port....
int port = prefs.getInt("Port", 4000);
logger.config("Server configured on port " + port + " (default: 4000)");
InetSocketAddress isa = new InetSocketAddress(
InetAddress.getLocalHost(), port);
serverChannel.socket().bind(isa);
} catch (IOException ioe) {
logger.severe ("IOException during server initialization!");
logger.exiting("jamb.server.Server", "init");
public void run() {
logger.entering("jamb.server.Server", "run");
int bufferSize = prefs.getInt("BufferSize", 8);
logger.config("Buffer size set to " + bufferSize + " (default: 8)");
SelectionKey acceptKey = null;
try {
acceptKey = serverChannel.register(
selector, SelectionKey.OP_ACCEPT);
} catch (ClosedChannelException cce) {
try {
while (acceptKey.selector().select() > 0) {
Set readyKeys = selector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
//logger.finest("Processing keys...");
//Get the key from the set and remove it
SelectionKey currentKey = (SelectionKey) i.next();
i.remove();
if (currentKey.isAcceptable()) {
logger.finest("Accepting key...");
acceptKey(currentKey);
} else if (currentKey.isReadable()) {
logger.finest("Reading key...");
readKey(currentKey, bufferSize);
} else if (currentKey.isWritable()) {
//logger.finest("Writing key...");
writeKey(currentKey);
} catch (IOException ioe) {
logger.warning("IOException during key handling!");
logger.exiting("jamb.server.Server", "run");
public void flushClient (Client client) {
try {
ByteBuffer buf = ByteBuffer.wrap( client.getOutputBuffer().toString().getBytes());
client.getChannel().write(buf);
} catch (IOException ioe) {
System.out.println ("Error writing to player");
client.setOutputBuffer(new StringBuffer());
private void acceptKey (SelectionKey acceptKey) {
logger.entering("jamb.server.Server", "acceptKey");
//Retrieve a SocketChannel for the new client, and register a new selector with
//read/write interests, and then register
try {
SocketChannel channel = ((ServerSocketChannel) acceptKey.channel()).accept();
channel.configureBlocking(false);
SelectionKey readKey = channel.register(
selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE );
readKey.attach(new Client(this, channel));
} catch (IOException ioe) {
System.out.println ("Error accepting key");
logger.exiting("jamb.server.Server", "acceptKey");
private void readKey (SelectionKey readKey, int bufSize) {
logger.entering("jamb.server.Server", "readKey");
Client client = (Client) readKey.attachment();
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);
int nbytes = client.getChannel().read( byteBuffer );
byteBuffer.flip();
Charset charset = Charset.forName( "us-ascii" );
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(byteBuffer);
String text = charBuffer.toString();
client.getInputBuffer().append(text);
if ( text.indexOf( "\n" ) >= 0 )
client.input();
} catch (IOException ioe) {
logger.warning("Unexpected quit...");
client.disconnect();
logger.exiting("jamb.server.Server", "readKey");
private void writeKey (SelectionKey writeKey) {
//logger.entering("jamb.server.Server", "writeKey");
Client client = (Client) writeKey.attachment();
if (!client.isConnected()) {
client.connect();
//logger.exiting("jamb.server.Server", "writeKey");From my own expierence with the NIO (Under Windows XP/ jdk1.4.1_01); you can't seem to set READ and WRITE at the same time.
The program flow I usually end up with for a echo server is:
When the selector.isAcceptable(): accept a connection; register for READs
In the read event; write the incoming characters to a buffer; register for a WRITE and add the buffer as an attachment.
In the write event; write the data to the socket If all the data was written; register for a READ; otherwise register for another WRITE so that you can write the rest.
Not sure if that the "proper" way; but it works well for me.
- Chris -
What is wrong with my non-blocking client?
I have two classes here, my abstract base class SingleSocketHandler, and its concrete subclass SingleSocketHandlerImpl. The subclass implements the protocol and parsing of my server.
For some reason, my server is not receiving the packet my client sends to it, and my client is getitng nothing in return (which makes sense, the server is supposed to respond to the logon packet). I make it non-blocking AFTER logon, so I knwo that this is not a problem. Can you see why my server is not receiving the packet my client writes to it? Did I not configure some setting with the SocketChannel that enables it to write? I am sort of unfamiliar with the java.nio.channels package, so the problem may be related to a setting in the SocketChannel or whatnot that I haven't configured.
NOTE: My chat server works fine with my blocking, multi-threaded test clients. Just not for my non-blocking client. The original problem for my blocking clients was that once the server stopped sending them data, they'd get caught in the in.read() loop and never get out of it. That's why I turned to non-blocking.
Just to remind you, my question is: why isn't my client sending the logon packet AND/OR my server receiving+responding to it?
public abstract class SingleSocketHandler extends Thread
/* Subclasses must implement these methods
/* Even though they're not a (public) interface */
/** <------------------------------- */
abstract void parse(int num);
abstract void parseNext();
abstract void doLogon();
/** -------------------------------> */
private SocketChannel sock;
/* Queues for in and out buffers */
private LinkedList <ByteBuffer> qIn;
private LinkedList <ByteBuffer> qOut;
/* Server info */
private String hostname;
private int port;
/* Flags */
protected int flags;
protected final int LOGGED_ON = 0x01;
* Default Constructor
protected SingleSocketHandler()
initQs();
* Constructor that sets socket info
* @param hostname
* @param port
* @param connect
protected SingleSocketHandler(String hostname, int port, boolean connect)
initQs();
if (connect)
connect(hostname, port);
else
setSocket(hostname, port);
* Switches off between reading and writing
protected void handleIO()
try
sock.configureBlocking(false);
} catch (IOException e)
// TODO
readInBuffers(1);
writeOutBuffers(1);
* Read in specified number of buffers into in queue
* Call for parsing
* @param num
protected void readInBuffers(int num)
Reporter.println("READING BUFFER");
for (int i = 0; i < num; i++)
ByteBuffer header = ByteBuffer.allocate(ProtocolCheck.HEADER_LEN);
try
Reporter.println("Reading header...");
sock.read(header);
Reporter.println("Read header.");
} catch (IOException e)
// TODO
/* Only add packet to in queue if it has a valid header */
if (ProtocolCheck.validHeader(header.array()))
Reporter.println("valid header");
ByteBuffer packet = ByteBuffer.allocate(ProtocolCheck.findPacketLen(header.array()));
packet.put(header);
try
Reporter.println("Reading rest of packet...");
sock.read(packet);
Reporter.println("Read packet.");
} catch (IOException e)
// TODO
addInBuffer(packet);
* Write out specified number of buffers from out queue
* And remove from out queue
* @param num
protected void writeOutBuffers(int num)
Reporter.println("WRITING BUFFER");
int i = 0;
while (qOut.size() > 0 && i < num)
try
sock.write(nextOutBuffer());
Reporter.println("Wrote buffer.");
} catch (IOException e)
// TODO
i++;
* Returns and removes next buffer from in queue
* @return ByteBuffer
protected ByteBuffer nextInBuffer()
return qIn.remove();
* Returns and removes next buffer from out queue
* @return ByteBuffer
protected ByteBuffer nextOutBuffer()
return qOut.remove();
* Sees if there is anohter in buffer
* @return boolean
protected boolean hasNextInBuffer()
return qIn.size() > 0;
* Sees if there is another out buffer
* @return ByteBuffer
protected boolean hasNextOutBuffer()
return qOut.size() > 0;
* Add a buffer to in queue
* @param b
public void addInBuffer(ByteBuffer b)
qIn.add(b);
* Add a buffer to in queue
* @param b
public void addInBuffer(Bufferable b)
qIn.add(b.getByteBuffer());
* Add a buffer to out queue
* @param b
public void addOutBuffer(ByteBuffer b)
qOut.add(b);
* Add a buffer to out queue
* @param b
public void addOutBuffer(Bufferable b)
qOut.add(b.getByteBuffer());
* Instantiate queues
protected void initQs()
qIn = new LinkedList <ByteBuffer> ();
qOut = new LinkedList <ByteBuffer> ();
* Set socket info then call connect()
* @param hostname
* @param port
public void connect(String hostname, int port)
setSocket(hostname, port);
connect();
* Connect to server
public void connect()
try
sock = SocketChannel.open();
sock.configureBlocking(true);
sock.connect(new InetSocketAddress(hostname, port));
while (!sock.finishConnect())
} catch (IOException e)
// TODO
* Disconnect from server
public void disconnect()
try
sock.close();
} catch (IOException e)
// TODO
* Set socket info without connecting
* @param hostname
* @param port
public void setSocket(String hostname, int port)
this.hostname = hostname;
this.port = port;
* @return state of connection
public boolean isConnected()
return (sock != null && sock.isConnected());
* @return state of being logged on
public boolean isLoggedOn()
return (sock != null && (flags & LOGGED_ON) == LOGGED_ON);
public final class SingleSocketHandlerImpl extends SingleSocketHandler
private UserDatabase <User> users;
* Constructor that does not set socket info
public SingleSocketHandlerImpl(UserDatabase <User> users)
super();
this.users = users;
* Constructor that does set socket info
* @param hostname
* @param port
* @param connect
public SingleSocketHandlerImpl(String hostname, int port, boolean connect, UserDatabase <User> users)
super(hostname, port, connect);
this.users = users;
* Thread's run method (base class extends Thread)
public void run()
doLogon();
while (isConnected() && isLoggedOn())
handleIO();
* Parses specified number of buffers from in queue
* @param num
/* (non-Javadoc)
* @see client.SingleSocketHandler#parseNext()
@Override
protected void parse(int num)
Reporter.println("Parse(int num) called.");
int i = 0;
while (hasNextInBuffer() && i < num)
parseNext();
i++;
/* (non-Javadoc)
* @see client.SingleSocketHandler#parseNext()
@Override
protected void parseNext()
Reporter.println("Parsing!");
if (!hasNextInBuffer())
Reporter.println("NO IN BUFFER.");
return;
/* Get buffer to work with */
ByteBuffer inBuffer = nextInBuffer();
byte[] data = inBuffer.array();
/* Decide what to do based on message ID */
byte msgid = data[1];
switch (msgid) {
case 0x01:
Reporter.println("0x01 packet.");
/* Determine success of login */
byte success = data[3];
if (success == (byte) 1)
flags |= LOGGED_ON;
Reporter.println("Logged on!");
else
flags &= ~LOGGED_ON;
Reporter.println(" <eChat> Unable to logon. Check the hostname and port settings.");
break;
case 0x02:
/* Parse out text message */
byte[] txtmsgbytes = new byte[data.length - 3];
System.arraycopy(data, 3, txtmsgbytes, 0, txtmsgbytes.length);
String txtmsg = new String(txtmsgbytes);
Reporter.println(txtmsg);
break;
case 0x03:
System.out.println("Packet ID not yet handled.");
break;
case 0x04:
System.out.println("Packet ID not yet handled.");
break;
default:
System.out.println("validID() method is buggy.");
* I make it non-blocking after logon sequences
/* (non-Javadoc)
* @see client.SingleSocketHandler#doLogon()
@Override
protected void doLogon()
Reporter.println("DOING LOGON!");
User myUser = users.getCurr();
addOutBuffer(new ScpLogon(myUser.getUsername(), myUser.getPassword()));
writeOutBuffers(1);
readInBuffers(1);
parseNext();
}Oh, if this helps, this is what gets output to my GUI. I did a lot of outputs for debugging purposes.
[3:29:27 PM]: Connecting...
[3:29:27 PM]: Connected!
[3:29:27 PM]: Logging on...
[3:29:27 PM]: DOING LOGON!
[3:29:27 PM]: WRITING BUFFER
[3:29:27 PM]: Wrote buffer.
[3:29:27 PM]: READING BUFFER
[3:29:27 PM]: Reading header... -
NIO non-blocking i/o- Any advantages for UDP server??
Hi,
I am developing a classic UDP-based server which serves hundreds of clients simultaneously. After receiving a simple request from a client, the server replies with a simple response (messages are no larger than 50 bytes).
What, if any non-blocking-related advantages would there be in using nio? Specifically, if I used select() without turning on non-blocking on the data channel, what do I lose?
The architecture consists of only one socket for responding to client requests. It uses receive() and send(), not read()/write()/connect().
Thanks in advance,
Dan.>>
What, if any non-blocking-related advantageswould
there be in using nio? Specifically, if I used
select() without turning on non-blocking on thedata
channel, what do I lose?You cannot do this. The runtime will throw an
IllegalBlockingModeException when you tried to
register it.
So in order to use select(), your registered channels must
be in non-blocking mode? Why? That's just the way it is?
So to conclude, using non-blocking mode provides no real advantage for
my application. It is only required or else I would not be able to use
select(), right? If so, what is so good about nio? Can you give an example that is similar to my application which would benefit from the non-blocking characteristic of nio?
Thanks for your help so far...
Daniel.
>>
The architecture consists of only one socket for
responding to client requests. It uses receive()and
send(), not read()/write()/connect().If you are only reading from one socket there are
theoretical advantages to servicing requests on more
than one thread, but you would not use non-blocking
mode to do this.
However I think some operating systems have
performance problems when doing this. Look at this
article under accept serialization:
http://httpd.apache.org/docs/misc/perf-tuning.html
The same problems may apply to multi-thread udp socket
readers. -
NIO: Strange problem when using ByteBuffer with non-blocking SocketChannel
Hi,
I have a server that uses multiplexed, non-blocking I/O with java.nio. When a client connects, the server waits for the message: <system cmd="knock"/>, returns a message and disconnects the client. The clients are shortly serviced in less than a second.
But the server newer receive anything from about 20% of the clients - even though it is sent. Or with other words: it is received and the data is contained in the ByteBuffer - SocketChannel.read(ByteBuffer) - but a call to ByteBuffer.remaing() returns 0 !!
ByteBuffer receiveBuf = ByteBuffer.allocate(65536);
receiveBuf.clear(); // the code is elsewhere used for longer living clients
int readBytes = channel.read(receiveBuf);
receiveBuf.flip();
StringBuffer sb = new StringBuffer();
System.out.println(" * Remaining: "+receiveBuf.remaining()); // writes: ' * Remaining: 0'
System.out.println(" * Received: "+new String(receiveBuf.array())); // writes: ' * Received: <system cmd="knock"/>'
while(receiveBuf.remaining() >= 2) {
byte b = receiveBuf.get();
sb.append((char)b);
System.out.println(" * sb content: "+sb.toString()); // writes: ' * sb content: 'The ByteBuffer clearly receives the correct data, but the ByteBuffer.remaining() returns 0 and therefore the StringBuffer will never have any content.
The problem seems to occur randomly and for about 20% of the clients (simulated from the same computer and therefore has the same bandwidth and so on).
Anyone knows what is going on, and how to solve the problem !?It's always possible in any read that the number of bytes read is less than the number of bytes requested. You need to keep reading until you have got everything you expected, and cope with every possible error condition on each iteration.
EJP -
SELECT of OCILobLocator in Non Blocking mode
Hi all.
I have problem:
I try select BLOB field into OCILobLocator* buffer in Non Blocking mode, and receive 'ORA-03106: fatal two-task communication protocol error' sometimes.
Details:
Application contains two threads : 1. select blob field, 2. update it.
I tried separate update and select to different apps (and run its in one time) - problem reproduced.
problem reproduced for OCIStmtFetch and OCIStmtFetch2.
If disable non blocking mode - problem disappear.
if error appear - record level error code contains 1405. Need wait few minutes for error message appearing (~1 minute in my case).
Using of OCI_DEFAULT in OCIDefineByPos instead OCI_DYNAMIC_FETCH don't solve problem.
I use oracle server and client library with version 10.2.0.4
Output sample:
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #877: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #54: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #877: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #54: 1405
Can anybody help me ?
m.b. exists workaround ?
#include <iostream>
#include <sstream>
#include <assert.h>
#include <oci.h>
#define _DYN 1
before run this test run next sql at DB:
CREATE TABLE ADSERVERTEST_BLOB(id NUMBER(10), text BLOB);
BEGIN
FOR i IN 0..999 LOOP
INSERT INTO ADSERVERTEST_BLOB(id, text) VALUES(i, utl_raw.cast_to_raw('init'));
END LOOP;
END;
template<typename Type, unsigned long TypeId>
class OCIHandlePtr
public:
OCIHandlePtr(): handle_(0) {}
OCIHandlePtr(Type* handle): handle_(handle) {}
~OCIHandlePtr()
reset(0);
void reset(Type* handle)
if(handle_)
sword result;
if((result = OCIHandleFree(
handle_,
TypeId)) != OCI_SUCCESS)
assert(0);
std::cerr << "Can't make OCIHandleFree" << std::endl;
handle_ = handle;
Type* get()
return handle_;
Type*& fill()
reset(0);
return handle_;
private:
Type* handle_;
template<typename Type, unsigned long TypeId>
class OCIDescriptorPtr
public:
OCIDescriptorPtr(): handle_(0) {}
OCIDescriptorPtr(Type* handle): handle_(handle) {}
~OCIDescriptorPtr()
reset(0);
void reset(Type* handle)
if(handle_)
sword result;
if((result = OCIDescriptorFree(
handle_,
TypeId)) != OCI_SUCCESS)
std::cerr << "Can't make OCIDescriptorFree" << std::endl;
handle_ = handle;
Type* get()
return handle_;
Type*& fill()
reset(0);
return handle_;
private:
Type* handle_;
void throw_oci_error(
const char* fun,
const char* oci_op,
long status,
OCIError* oci_error_handler,
const char* query = 0)
std::cerr << fun << ": can't make " << oci_op << ": status = " << status;
if(status == OCI_SUCCESS_WITH_INFO ||
status == OCI_ERROR)
std::cerr << ", message = '";
text err_buf[1024] = "";
sb4 err_code = 0;
OCIErrorGet(
oci_error_handler,
(ub4)1,
0,
&err_code,
err_buf,
sizeof(err_buf),
(ub4)OCI_HTYPE_ERROR);
std::cerr << err_buf << "', error code = " << err_code;
exit(1);
if(query)
std::cerr << ", sql = " << query;
OCIHandlePtr<OCIEnv, OCI_HTYPE_ENV> environment_handle;
void connect(
OCIEnv* environment_handle,
const char* db,
const char* user,
const char* password,
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR>& error_handle,
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER>& server_handle,
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION>& session_handle,
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX>& svc_context_handle)
static const char* FUN = "connect()";
sword result;
// allocate an error handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &error_handle.fill(),
OCI_HTYPE_ERROR,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// allocate a server handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &server_handle.fill(),
OCI_HTYPE_SERVER,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
if((result = OCIServerAttach(
server_handle.get(),
error_handle.get(),
(text*)db,
strlen(db),
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIServerAttach", result, error_handle.get());
// allocate a service handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &svc_context_handle.fill(),
OCI_HTYPE_SVCCTX,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// set the server attribute in the service context handle
if((result = OCIAttrSet(
svc_context_handle.get(),
OCI_HTYPE_SVCCTX,
server_handle.get(),
sizeof(OCIServer*),
OCI_ATTR_SERVER,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// allocate a user session handle
if((result = OCIHandleAlloc(
environment_handle,
(void **)&session_handle.fill(),
OCI_HTYPE_SESSION,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// set username and password attributes in user session handle
if((result = OCIAttrSet(
session_handle.get(),
OCI_HTYPE_SESSION,
(text*)user,
strlen(user),
OCI_ATTR_USERNAME,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
if((result = OCIAttrSet(
session_handle.get(),
OCI_HTYPE_SESSION,
(text*)password,
strlen(password),
OCI_ATTR_PASSWORD,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
// start the session
if((result = OCISessionBegin(
svc_context_handle.get(),
error_handle.get(),
session_handle.get(),
OCI_CRED_RDBMS,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCISessionBegin", result, error_handle.get());
// set the user session attribute in the service context handle
if((result = OCIAttrSet(
svc_context_handle.get(),
OCI_HTYPE_SVCCTX,
session_handle.get(),
sizeof(OCISession*),
OCI_ATTR_SESSION,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
ub1 attr_value = 1;
if((result = OCIAttrSet(
server_handle.get(),
OCI_HTYPE_SERVER,
&attr_value,
sizeof(attr_value),
OCI_ATTR_NONBLOCKING_MODE,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
void disconnect(
OCIEnv* environment_handle,
OCIError* error_handle,
OCIServer* server_handle,
OCISession* session_handle,
OCISvcCtx* svc_context_handle)
static const char* FUN = "disconnect()";
sword result;
if((result = OCISessionEnd(
svc_context_handle,
error_handle,
session_handle,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCISessionEnd", result, error_handle);
if((result = OCIServerDetach(
server_handle,
error_handle,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIServerDetach", result, error_handle);
OCILobLocator* FETCH_BUFFER_1[10000*1024];
char IND_BUFFER_1[10000*1024];
ub2 ERROR_BUFFER_1[1024];
OCIDefine* define_handle_1;
void clear_blob_buf(
OCILobLocator** buf,
unsigned long fetch_size)
for(unsigned long i = 0; i < 1024; ++i)
OCIDescriptorFree(
buf,
(ub4)OCI_DTYPE_LOB);
::memset(buf, 0, fetch_size * 1024);
uint32_t RET_LEN4;
sb4 oci_blob_callback(
dvoid* ctx,
OCIDefine* define,
ub4 iter,
dvoid** bufpp,
ub4** alenpp,
ub1* piecep,
dvoid** indpp,
ub2** rcodepp)
RET_LEN4 = sizeof(OCILobLocator*);
*bufpp = FETCH_BUFFER_1[iter];
*alenpp = &RET_LEN4;
*piecep = OCI_ONE_PIECE;
*indpp = IND_BUFFER_1 + iter;
*rcodepp = ERROR_BUFFER_1 + iter;
//std::cout << "iter: " << iter << std::endl;
return OCI_CONTINUE;
int define_column(
OCIEnv* environment_handle,
OCISvcCtx* svc_handle,
OCIStmt* stmt_handle,
OCIError* error_handle,
OCIDefine** define_handle,
unsigned long pos,
long oci_type,
unsigned long fetch_size,
OCILobLocator** buf,
char* ind_buf,
ub2* err_buf)
static const char* FUN = "define_column()";
sword result;
if(oci_type == SQLT_BLOB)
::memset(buf, 0, fetch_size * 1024);
for(int i = 0; i < 1024; ++i)
if((result = OCIDescriptorAlloc(
(dvoid*)environment_handle,
(dvoid**)&buf[i],
(ub4)OCI_DTYPE_LOB,
(size_t)0,
(dvoid**)0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDescriptorAlloc", result, error_handle);
ub2 size = 0;
OCIDescriptorPtr<OCIParam, OCI_DTYPE_PARAM> param_handle;
// ub2 oci_data_type = 0;
if((result = OCIParamGet(
stmt_handle,
OCI_HTYPE_STMT,
error_handle,
reinterpret_cast<void**>(¶m_handle.fill()),
pos)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIParamGet", result, error_handle);
if((result = OCIAttrGet(
param_handle.get(),
OCI_DTYPE_PARAM,
&size,
0,
OCI_ATTR_DATA_SIZE,
error_handle)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle);
if((result = OCIDefineByPos(
stmt_handle,
define_handle,
error_handle,
pos,
# ifdef _DYN
0,
-1,
#else
buf,
fetch_size,
#endif
oci_type,
ind_buf,
0,
err_buf, // ptr to array of column-level return codes
# ifdef _DYN
OCI_DYNAMIC_FETCH
# else
OCI_DEFAULT
# endif
)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDefineByPos", result, error_handle);
# ifdef _DYN
if((result = OCIDefineDynamic(
*define_handle,
error_handle,
0,
oci_blob_callback)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDefineByPos", result, error_handle);
# endif
return 0;
int define_columns(
OCIEnv* environment_handle,
OCISvcCtx* svc_handle,
OCIStmt* stmt_handle,
OCIError* error_handle)
static const char* FUN = "define_columns()";
define_handle_1 = 0;
int pos = 1;
::memset(ERROR_BUFFER_1, 0, 1024 * sizeof(ERROR_BUFFER_1[0]));
define_column(
environment_handle,
svc_handle,
stmt_handle,
error_handle,
&define_handle_1,
pos++,
SQLT_BLOB,
sizeof(OCILobLocator*),
FETCH_BUFFER_1,
IND_BUFFER_1,
ERROR_BUFFER_1);
return 0;
int execute_select(
const char* db,
const char* user,
const char* password)
static const char* FUN = "execute_select()";
const unsigned long FETCH_COUNT = 1024;
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR> error_handle;
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER> server_handle;
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION> session_handle;
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX> svc_context_handle;
connect(
environment_handle.get(),
db,
user,
password,
error_handle,
server_handle,
session_handle,
svc_context_handle);
OCIHandlePtr<OCIStmt, OCI_HTYPE_STMT> stmt_handle;
sword result;
if((result = OCIHandleAlloc(
environment_handle.get(),
(void**)&stmt_handle.fill(),
OCI_HTYPE_STMT,
0,
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
const char QUERY[] = "SELECT text FROM ADSERVERTEST_BLOB";
ub4 rows = 0;
if((result = OCIAttrSet(
stmt_handle.get(),
OCI_HTYPE_STMT,
(dvoid *)&rows,
(ub4)sizeof(ub4),
OCI_ATTR_PREFETCH_ROWS,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(
FUN, "OCIAttrSet(OCI_ATTR_PREFETCH_ROWS)", result, error_handle.get());
if((result = OCIStmtPrepare(
stmt_handle.get(),
error_handle.get(),
(text*)QUERY,
strlen(QUERY),
OCI_NTV_SYNTAX,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIStmtPrepare", result, error_handle.get());
ub2 stmt_type;
if((result = OCIAttrGet(
stmt_handle.get(),
OCI_HTYPE_STMT,
&stmt_type,
0,
OCI_ATTR_STMT_TYPE,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle.get());
ub4 prev_fetched = 0;
while((result = OCIStmtExecute(
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get(),
0,
0,
0,
0,
OCI_DEFAULT)) != OCI_SUCCESS)
if(result != OCI_STILL_EXECUTING)
throw_oci_error(FUN, "OCIStmtExecute", result, error_handle.get());
define_columns(
environment_handle.get(),
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get());
ub4 all_fetched_count = 0;
while(true)
while((result = OCIStmtFetch2(
stmt_handle.get(),
error_handle.get(),
FETCH_COUNT,
OCI_FETCH_NEXT,
1,
OCI_DEFAULT)) == OCI_STILL_EXECUTING
# ifdef _DYN
// || result == OCI_NEED_DATA
# endif
if (result != OCI_SUCCESS &&
result != OCI_NO_DATA &&
result != OCI_SUCCESS_WITH_INFO)
std::cerr << FUN << ": can't make OCIStmtFetch2: status = " << result;
std::cerr << ", message = '";
text err_buf[1024] = "";
sb4 err_code = 0;
OCIErrorGet(
error_handle.get(),
(ub4)1,
0,
&err_code,
err_buf,
sizeof(err_buf),
(ub4)OCI_HTYPE_ERROR);
std::cerr << err_buf << "', error code = " << err_code << ", row errors: ";
for(const ub2* cur = ERROR_BUFFER_1;
cur < ERROR_BUFFER_1 + 1024; ++cur)
if(*cur)
std::cerr << "#" << (cur - ERROR_BUFFER_1) << ": " <<
*cur << std::endl;
ub4 fetched_count = 0;
if((result = OCIAttrGet (
stmt_handle.get(),
OCI_HTYPE_STMT,
&fetched_count,
0,
OCI_ATTR_ROW_COUNT,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle.get());
all_fetched_count += fetched_count;
if(fetched_count > 0)
for(unsigned long i = 0; i < fetched_count - 1; ++i)
ub4 lob_size;
while((result = OCILobGetLength(
svc_context_handle.get(),
error_handle.get(),
FETCH_BUFFER_1[i],
&lob_size)) == OCI_STILL_EXECUTING)
if(result != OCI_SUCCESS)
throw_oci_error(FUN, "OCILobGetLength", result, error_handle.get());
std::cout << "#" << i << ": ind = " << (unsigned long)IND_BUFFER_1[i] <<
", len = " << lob_size << std::endl;
if(fetched_count - prev_fetched < FETCH_COUNT)
break;
prev_fetched = fetched_count;
clear_blob_buf(
FETCH_BUFFER_1,
sizeof(OCILobLocator*));
while((result = OCIStmtFetch(
stmt_handle.get(),
error_handle.get(),
0,
OCI_FETCH_NEXT,
OCI_DEFAULT)) == OCI_STILL_EXECUTING
disconnect(
environment_handle.get(),
error_handle.get(),
server_handle.get(),
session_handle.get(),
svc_context_handle.get());
return 0;
int execute_update(
const char* db,
const char* user,
const char* password)
static const char* FUN = "execute_update()";
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR> error_handle;
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER> server_handle;
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION> session_handle;
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX> svc_context_handle;
connect(
environment_handle.get(),
db,
user,
password,
error_handle,
server_handle,
session_handle,
svc_context_handle);
OCIHandlePtr<OCIStmt, OCI_HTYPE_STMT> stmt_handle;
for(int i = 0; i < 1000; ++i)
sword result;
if((result = OCIHandleAlloc(
environment_handle.get(),
(void**)&stmt_handle.fill(),
OCI_HTYPE_STMT,
0,
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
std::ostringstream sql;
std::string str;
std::string et("\xEB\xB2\x88");
unsigned long rep = ::rand() % 500 + 1;
str.reserve(rep*et.size());
for(unsigned long ei = 0; ei < rep; ++ei)
str.append(et);
sql << "BEGIN " <<
"UPDATE ADSERVERTEST_BLOB SET text = "
"utl_raw.cast_to_raw('" << str << "') "
"WHERE id = " << i <<
"END;";
if((result = OCIStmtPrepare(
stmt_handle.get(),
error_handle.get(),
(text*)sql.str().c_str(),
sql.str().length(),
OCI_NTV_SYNTAX,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIStmtPrepare", result, error_handle.get());
while((result = OCIStmtExecute(
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get(),
1,
0,
0,
0,
OCI_DEFAULT)) != OCI_SUCCESS)
if(result != OCI_STILL_EXECUTING)
throw_oci_error(FUN, "OCIStmtExecute", result, error_handle.get());
disconnect(
environment_handle.get(),
error_handle.get(),
server_handle.get(),
session_handle.get(),
svc_context_handle.get());
return 0;
void* select_thread(void* ctx)
while(true)
execute_select(
"//oraclept.ocslab.com/addbpt.ocslab.com",
"bs_unittest_4",
"adserver");
// std::cout << "select finished" << std::endl;
return ctx;
void* update_thread(void* ctx)
while(true)
execute_update(
"//oraclept.ocslab.com/addbpt.ocslab.com",
"bs_unittest_4",
"adserver");
// std::cout << "update finished" << std::endl;
return ctx;
int main()
static const char* FUN = "main()";
sword result;
// allocate an environment handle
if((result = OCIEnvCreate(
&environment_handle.fill(),
OCI_OBJECT | OCI_THREADED,
0, // context
0, // malloc
0, // realloc
0, // free
0, // extra memory to allocate
0) // pointer to user-memory
) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIEnvCreate", result, 0);
pthread_t th1, th2;
pthread_create(&th1, 0, select_thread, 0);
pthread_create(&th2, 0, update_thread, 0);
pthread_join(th1, 0);
pthread_join(th2, 0);
return 0;
Edited by: user13011391 on 20.04.2010 5:50
Edited by: user13011391 on 20.04.2010 6:00
Edited by: user13011391 on 20.04.2010 6:15Hi all.
I have problem:
I try select BLOB field into OCILobLocator* buffer in Non Blocking mode, and receive 'ORA-03106: fatal two-task communication protocol error' sometimes.
Details:
Application contains two threads : 1. select blob field, 2. update it.
I tried separate update and select to different apps (and run its in one time) - problem reproduced.
problem reproduced for OCIStmtFetch and OCIStmtFetch2.
If disable non blocking mode - problem disappear.
if error appear - record level error code contains 1405. Need wait few minutes for error message appearing (~1 minute in my case).
Using of OCI_DEFAULT in OCIDefineByPos instead OCI_DYNAMIC_FETCH don't solve problem.
I use oracle server and client library with version 10.2.0.4
Output sample:
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #877: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #54: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #877: 1405
execute_select(): can't make OCIStmtFetch2: status = -1, message = 'ORA-03106: fatal two-task communication protocol error
', error code = 3106, row errors: #54: 1405
Can anybody help me ?
m.b. exists workaround ?
#include <iostream>
#include <sstream>
#include <assert.h>
#include <oci.h>
#define _DYN 1
before run this test run next sql at DB:
CREATE TABLE ADSERVERTEST_BLOB(id NUMBER(10), text BLOB);
BEGIN
FOR i IN 0..999 LOOP
INSERT INTO ADSERVERTEST_BLOB(id, text) VALUES(i, utl_raw.cast_to_raw('init'));
END LOOP;
END;
template<typename Type, unsigned long TypeId>
class OCIHandlePtr
public:
OCIHandlePtr(): handle_(0) {}
OCIHandlePtr(Type* handle): handle_(handle) {}
~OCIHandlePtr()
reset(0);
void reset(Type* handle)
if(handle_)
sword result;
if((result = OCIHandleFree(
handle_,
TypeId)) != OCI_SUCCESS)
assert(0);
std::cerr << "Can't make OCIHandleFree" << std::endl;
handle_ = handle;
Type* get()
return handle_;
Type*& fill()
reset(0);
return handle_;
private:
Type* handle_;
template<typename Type, unsigned long TypeId>
class OCIDescriptorPtr
public:
OCIDescriptorPtr(): handle_(0) {}
OCIDescriptorPtr(Type* handle): handle_(handle) {}
~OCIDescriptorPtr()
reset(0);
void reset(Type* handle)
if(handle_)
sword result;
if((result = OCIDescriptorFree(
handle_,
TypeId)) != OCI_SUCCESS)
std::cerr << "Can't make OCIDescriptorFree" << std::endl;
handle_ = handle;
Type* get()
return handle_;
Type*& fill()
reset(0);
return handle_;
private:
Type* handle_;
void throw_oci_error(
const char* fun,
const char* oci_op,
long status,
OCIError* oci_error_handler,
const char* query = 0)
std::cerr << fun << ": can't make " << oci_op << ": status = " << status;
if(status == OCI_SUCCESS_WITH_INFO ||
status == OCI_ERROR)
std::cerr << ", message = '";
text err_buf[1024] = "";
sb4 err_code = 0;
OCIErrorGet(
oci_error_handler,
(ub4)1,
0,
&err_code,
err_buf,
sizeof(err_buf),
(ub4)OCI_HTYPE_ERROR);
std::cerr << err_buf << "', error code = " << err_code;
exit(1);
if(query)
std::cerr << ", sql = " << query;
OCIHandlePtr<OCIEnv, OCI_HTYPE_ENV> environment_handle;
void connect(
OCIEnv* environment_handle,
const char* db,
const char* user,
const char* password,
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR>& error_handle,
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER>& server_handle,
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION>& session_handle,
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX>& svc_context_handle)
static const char* FUN = "connect()";
sword result;
// allocate an error handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &error_handle.fill(),
OCI_HTYPE_ERROR,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// allocate a server handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &server_handle.fill(),
OCI_HTYPE_SERVER,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
if((result = OCIServerAttach(
server_handle.get(),
error_handle.get(),
(text*)db,
strlen(db),
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIServerAttach", result, error_handle.get());
// allocate a service handle
if((result = OCIHandleAlloc(
environment_handle,
(void **) &svc_context_handle.fill(),
OCI_HTYPE_SVCCTX,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// set the server attribute in the service context handle
if((result = OCIAttrSet(
svc_context_handle.get(),
OCI_HTYPE_SVCCTX,
server_handle.get(),
sizeof(OCIServer*),
OCI_ATTR_SERVER,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// allocate a user session handle
if((result = OCIHandleAlloc(
environment_handle,
(void **)&session_handle.fill(),
OCI_HTYPE_SESSION,
0, // extra memory to allocate
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
// set username and password attributes in user session handle
if((result = OCIAttrSet(
session_handle.get(),
OCI_HTYPE_SESSION,
(text*)user,
strlen(user),
OCI_ATTR_USERNAME,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
if((result = OCIAttrSet(
session_handle.get(),
OCI_HTYPE_SESSION,
(text*)password,
strlen(password),
OCI_ATTR_PASSWORD,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
// start the session
if((result = OCISessionBegin(
svc_context_handle.get(),
error_handle.get(),
session_handle.get(),
OCI_CRED_RDBMS,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCISessionBegin", result, error_handle.get());
// set the user session attribute in the service context handle
if((result = OCIAttrSet(
svc_context_handle.get(),
OCI_HTYPE_SVCCTX,
session_handle.get(),
sizeof(OCISession*),
OCI_ATTR_SESSION,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
ub1 attr_value = 1;
if((result = OCIAttrSet(
server_handle.get(),
OCI_HTYPE_SERVER,
&attr_value,
sizeof(attr_value),
OCI_ATTR_NONBLOCKING_MODE,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrSet", result, error_handle.get());
void disconnect(
OCIEnv* environment_handle,
OCIError* error_handle,
OCIServer* server_handle,
OCISession* session_handle,
OCISvcCtx* svc_context_handle)
static const char* FUN = "disconnect()";
sword result;
if((result = OCISessionEnd(
svc_context_handle,
error_handle,
session_handle,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCISessionEnd", result, error_handle);
if((result = OCIServerDetach(
server_handle,
error_handle,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIServerDetach", result, error_handle);
OCILobLocator* FETCH_BUFFER_1[10000*1024];
char IND_BUFFER_1[10000*1024];
ub2 ERROR_BUFFER_1[1024];
OCIDefine* define_handle_1;
void clear_blob_buf(
OCILobLocator** buf,
unsigned long fetch_size)
for(unsigned long i = 0; i < 1024; ++i)
OCIDescriptorFree(
buf,
(ub4)OCI_DTYPE_LOB);
::memset(buf, 0, fetch_size * 1024);
uint32_t RET_LEN4;
sb4 oci_blob_callback(
dvoid* ctx,
OCIDefine* define,
ub4 iter,
dvoid** bufpp,
ub4** alenpp,
ub1* piecep,
dvoid** indpp,
ub2** rcodepp)
RET_LEN4 = sizeof(OCILobLocator*);
*bufpp = FETCH_BUFFER_1[iter];
*alenpp = &RET_LEN4;
*piecep = OCI_ONE_PIECE;
*indpp = IND_BUFFER_1 + iter;
*rcodepp = ERROR_BUFFER_1 + iter;
//std::cout << "iter: " << iter << std::endl;
return OCI_CONTINUE;
int define_column(
OCIEnv* environment_handle,
OCISvcCtx* svc_handle,
OCIStmt* stmt_handle,
OCIError* error_handle,
OCIDefine** define_handle,
unsigned long pos,
long oci_type,
unsigned long fetch_size,
OCILobLocator** buf,
char* ind_buf,
ub2* err_buf)
static const char* FUN = "define_column()";
sword result;
if(oci_type == SQLT_BLOB)
::memset(buf, 0, fetch_size * 1024);
for(int i = 0; i < 1024; ++i)
if((result = OCIDescriptorAlloc(
(dvoid*)environment_handle,
(dvoid**)&buf[i],
(ub4)OCI_DTYPE_LOB,
(size_t)0,
(dvoid**)0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDescriptorAlloc", result, error_handle);
ub2 size = 0;
OCIDescriptorPtr<OCIParam, OCI_DTYPE_PARAM> param_handle;
// ub2 oci_data_type = 0;
if((result = OCIParamGet(
stmt_handle,
OCI_HTYPE_STMT,
error_handle,
reinterpret_cast<void**>(¶m_handle.fill()),
pos)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIParamGet", result, error_handle);
if((result = OCIAttrGet(
param_handle.get(),
OCI_DTYPE_PARAM,
&size,
0,
OCI_ATTR_DATA_SIZE,
error_handle)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle);
if((result = OCIDefineByPos(
stmt_handle,
define_handle,
error_handle,
pos,
# ifdef _DYN
0,
-1,
#else
buf,
fetch_size,
#endif
oci_type,
ind_buf,
0,
err_buf, // ptr to array of column-level return codes
# ifdef _DYN
OCI_DYNAMIC_FETCH
# else
OCI_DEFAULT
# endif
)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDefineByPos", result, error_handle);
# ifdef _DYN
if((result = OCIDefineDynamic(
*define_handle,
error_handle,
0,
oci_blob_callback)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIDefineByPos", result, error_handle);
# endif
return 0;
int define_columns(
OCIEnv* environment_handle,
OCISvcCtx* svc_handle,
OCIStmt* stmt_handle,
OCIError* error_handle)
static const char* FUN = "define_columns()";
define_handle_1 = 0;
int pos = 1;
::memset(ERROR_BUFFER_1, 0, 1024 * sizeof(ERROR_BUFFER_1[0]));
define_column(
environment_handle,
svc_handle,
stmt_handle,
error_handle,
&define_handle_1,
pos++,
SQLT_BLOB,
sizeof(OCILobLocator*),
FETCH_BUFFER_1,
IND_BUFFER_1,
ERROR_BUFFER_1);
return 0;
int execute_select(
const char* db,
const char* user,
const char* password)
static const char* FUN = "execute_select()";
const unsigned long FETCH_COUNT = 1024;
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR> error_handle;
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER> server_handle;
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION> session_handle;
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX> svc_context_handle;
connect(
environment_handle.get(),
db,
user,
password,
error_handle,
server_handle,
session_handle,
svc_context_handle);
OCIHandlePtr<OCIStmt, OCI_HTYPE_STMT> stmt_handle;
sword result;
if((result = OCIHandleAlloc(
environment_handle.get(),
(void**)&stmt_handle.fill(),
OCI_HTYPE_STMT,
0,
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
const char QUERY[] = "SELECT text FROM ADSERVERTEST_BLOB";
ub4 rows = 0;
if((result = OCIAttrSet(
stmt_handle.get(),
OCI_HTYPE_STMT,
(dvoid *)&rows,
(ub4)sizeof(ub4),
OCI_ATTR_PREFETCH_ROWS,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(
FUN, "OCIAttrSet(OCI_ATTR_PREFETCH_ROWS)", result, error_handle.get());
if((result = OCIStmtPrepare(
stmt_handle.get(),
error_handle.get(),
(text*)QUERY,
strlen(QUERY),
OCI_NTV_SYNTAX,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIStmtPrepare", result, error_handle.get());
ub2 stmt_type;
if((result = OCIAttrGet(
stmt_handle.get(),
OCI_HTYPE_STMT,
&stmt_type,
0,
OCI_ATTR_STMT_TYPE,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle.get());
ub4 prev_fetched = 0;
while((result = OCIStmtExecute(
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get(),
0,
0,
0,
0,
OCI_DEFAULT)) != OCI_SUCCESS)
if(result != OCI_STILL_EXECUTING)
throw_oci_error(FUN, "OCIStmtExecute", result, error_handle.get());
define_columns(
environment_handle.get(),
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get());
ub4 all_fetched_count = 0;
while(true)
while((result = OCIStmtFetch2(
stmt_handle.get(),
error_handle.get(),
FETCH_COUNT,
OCI_FETCH_NEXT,
1,
OCI_DEFAULT)) == OCI_STILL_EXECUTING
# ifdef _DYN
// || result == OCI_NEED_DATA
# endif
if (result != OCI_SUCCESS &&
result != OCI_NO_DATA &&
result != OCI_SUCCESS_WITH_INFO)
std::cerr << FUN << ": can't make OCIStmtFetch2: status = " << result;
std::cerr << ", message = '";
text err_buf[1024] = "";
sb4 err_code = 0;
OCIErrorGet(
error_handle.get(),
(ub4)1,
0,
&err_code,
err_buf,
sizeof(err_buf),
(ub4)OCI_HTYPE_ERROR);
std::cerr << err_buf << "', error code = " << err_code << ", row errors: ";
for(const ub2* cur = ERROR_BUFFER_1;
cur < ERROR_BUFFER_1 + 1024; ++cur)
if(*cur)
std::cerr << "#" << (cur - ERROR_BUFFER_1) << ": " <<
*cur << std::endl;
ub4 fetched_count = 0;
if((result = OCIAttrGet (
stmt_handle.get(),
OCI_HTYPE_STMT,
&fetched_count,
0,
OCI_ATTR_ROW_COUNT,
error_handle.get())) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIAttrGet", result, error_handle.get());
all_fetched_count += fetched_count;
if(fetched_count > 0)
for(unsigned long i = 0; i < fetched_count - 1; ++i)
ub4 lob_size;
while((result = OCILobGetLength(
svc_context_handle.get(),
error_handle.get(),
FETCH_BUFFER_1[i],
&lob_size)) == OCI_STILL_EXECUTING)
if(result != OCI_SUCCESS)
throw_oci_error(FUN, "OCILobGetLength", result, error_handle.get());
std::cout << "#" << i << ": ind = " << (unsigned long)IND_BUFFER_1[i] <<
", len = " << lob_size << std::endl;
if(fetched_count - prev_fetched < FETCH_COUNT)
break;
prev_fetched = fetched_count;
clear_blob_buf(
FETCH_BUFFER_1,
sizeof(OCILobLocator*));
while((result = OCIStmtFetch(
stmt_handle.get(),
error_handle.get(),
0,
OCI_FETCH_NEXT,
OCI_DEFAULT)) == OCI_STILL_EXECUTING
disconnect(
environment_handle.get(),
error_handle.get(),
server_handle.get(),
session_handle.get(),
svc_context_handle.get());
return 0;
int execute_update(
const char* db,
const char* user,
const char* password)
static const char* FUN = "execute_update()";
OCIHandlePtr<OCIError, OCI_HTYPE_ERROR> error_handle;
OCIHandlePtr<OCIServer, OCI_HTYPE_SERVER> server_handle;
OCIHandlePtr<OCISession, OCI_HTYPE_SESSION> session_handle;
OCIHandlePtr<OCISvcCtx, OCI_HTYPE_SVCCTX> svc_context_handle;
connect(
environment_handle.get(),
db,
user,
password,
error_handle,
server_handle,
session_handle,
svc_context_handle);
OCIHandlePtr<OCIStmt, OCI_HTYPE_STMT> stmt_handle;
for(int i = 0; i < 1000; ++i)
sword result;
if((result = OCIHandleAlloc(
environment_handle.get(),
(void**)&stmt_handle.fill(),
OCI_HTYPE_STMT,
0,
0)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIHandleAlloc", result, error_handle.get());
std::ostringstream sql;
std::string str;
std::string et("\xEB\xB2\x88");
unsigned long rep = ::rand() % 500 + 1;
str.reserve(rep*et.size());
for(unsigned long ei = 0; ei < rep; ++ei)
str.append(et);
sql << "BEGIN " <<
"UPDATE ADSERVERTEST_BLOB SET text = "
"utl_raw.cast_to_raw('" << str << "') "
"WHERE id = " << i <<
"END;";
if((result = OCIStmtPrepare(
stmt_handle.get(),
error_handle.get(),
(text*)sql.str().c_str(),
sql.str().length(),
OCI_NTV_SYNTAX,
OCI_DEFAULT)) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIStmtPrepare", result, error_handle.get());
while((result = OCIStmtExecute(
svc_context_handle.get(),
stmt_handle.get(),
error_handle.get(),
1,
0,
0,
0,
OCI_DEFAULT)) != OCI_SUCCESS)
if(result != OCI_STILL_EXECUTING)
throw_oci_error(FUN, "OCIStmtExecute", result, error_handle.get());
disconnect(
environment_handle.get(),
error_handle.get(),
server_handle.get(),
session_handle.get(),
svc_context_handle.get());
return 0;
void* select_thread(void* ctx)
while(true)
execute_select(
"//oraclept.ocslab.com/addbpt.ocslab.com",
"bs_unittest_4",
"adserver");
// std::cout << "select finished" << std::endl;
return ctx;
void* update_thread(void* ctx)
while(true)
execute_update(
"//oraclept.ocslab.com/addbpt.ocslab.com",
"bs_unittest_4",
"adserver");
// std::cout << "update finished" << std::endl;
return ctx;
int main()
static const char* FUN = "main()";
sword result;
// allocate an environment handle
if((result = OCIEnvCreate(
&environment_handle.fill(),
OCI_OBJECT | OCI_THREADED,
0, // context
0, // malloc
0, // realloc
0, // free
0, // extra memory to allocate
0) // pointer to user-memory
) != OCI_SUCCESS)
throw_oci_error(FUN, "OCIEnvCreate", result, 0);
pthread_t th1, th2;
pthread_create(&th1, 0, select_thread, 0);
pthread_create(&th2, 0, update_thread, 0);
pthread_join(th1, 0);
pthread_join(th2, 0);
return 0;
Edited by: user13011391 on 20.04.2010 5:50
Edited by: user13011391 on 20.04.2010 6:00
Edited by: user13011391 on 20.04.2010 6:15 -
Non blocking worker servlet ?
Hi friends,
I have an issue to implement. We implemented a web application and now I want to separate some parts of this application. I can express the action shorter and simple below.
if a user requests x-y ticket {
���try {
������check db if x-y is available
������if true send available
������else not
���}catch (NonExistentData) {
������addJob2Queue(x-y)
������send available
���}
class AvailabilityHelper extends Thread{
���run(){
������while(true){
���������checkQueue
���������if there is job, updateDBfor(org,dest)
������}
���}
* updateDBfor(org,dest) includes other ejb references to request data and insert it into db
This web aplication runs with JSP 1.2 EL support on WAS 5.1
the check for db and the thread implementation was in a seperate package and were used in actions of web application. Now they also want to use these checks for other (non web) applications. So i think there should be a session bean in ejb and should process these requests and I used JMS (Message-Driven Bean) with WebSphere MQ to undertake the thread and queue mechanism.
Now it works like this :
class exampleSessionBean{
���getAvalibability(org, dest){
������try {
���������check db if x-y is available
���������if true send available
���������else not
������}catch (NonExistentData) {
���������queueSender.sendMessage(update x-y)
���������send available;
������}
���}
class queueMDB{
���onMessage(){
������updateDBfor(org,dest)
���}
The purpose of this applications was, not to block the user for db update process, if there is data in db select and show to the user. the update process of db includes other ejb references and takes so much time. It is nonsense to make the user wait such time. And the info is not a big deal, because of this when i put a request for update, without blocking i send it as available...
So what is the problem ? :) Deployment team don't want to pay for websphere MQ and hire a admin for that. Also they don't want to use Embedded Messaging server client (JMS Server) of WAS. So I am asking you: is there a way to implement a non blocking servlet so that i will just make a request and don't wait for response, or a servlet will take the request and release the connection but will continue to process the request ?
thanks for all...I tried to implement a web application and add a ServletContextListener as stevejluke suggests. But on contextInitialized function when creating new JobConsumer it gets following errors on server.
6/27/06 12:51:36:391 CEST] 33238138 WebContainer A SRVE0169I: Loading Web Module: non-blocking.
[6/27/06 12:51:36:438 CEST] 33238138 SystemOut O OlaListener initializing...
[6/27/06 12:51:36:516 CEST] 33238138 SystemOut O OlaListener - Queue added
[6/27/06 12:51:36:516 CEST] 33238138 SystemOut O OlaListener - keepWorking
[6/27/06 12:51:36:672 CEST] 33238138 WebApp E SRVE0015E: Failure to initialize Web application non-blocking
[6/27/06 12:51:36:844 CEST] 33238138 WebGroup E SRVE0054E: An error occurred while loading Web application
public class OlaListener implements ServletContextListener {
* @see javax.servlet.ServletContextListener#void (javax.servlet.ServletContextEvent)
public void contextDestroyed(ServletContextEvent event) {
ServletContext context = event.getServletContext();
context.setAttribute("keepWorking", Boolean.FALSE);
* @see javax.servlet.ServletContextListener#void (javax.servlet.ServletContextEvent)
public void contextInitialized(ServletContextEvent event) {
System.out.println("OlaListener initializing...");
ServletContext context = event.getServletContext();
WorkQueue newJobs = new WorkQueue();
context.setAttribute("newJobs", newJobs);
System.out.println("OlaListener - Queue added");
context.setAttribute("keepWorking", Boolean.TRUE);
System.out.println("OlaListener - keepWorking");
JobConsumer jc = new JobConsumer();
System.out.println("OlaListener - Job Consumer created");
jc.setContext(context);
System.out.println("OlaListener - context set");
Thread t = new Thread(jc);
t.start();
public class JobConsumer implements Runnable{
/*log4j*/ private static final Logger logger = Logger.getLogger(JobConsumer.class);
private ServletContext context = null;
public void run(){
System.out.println("JobConsumer - run Start");
processQueue(context);
System.out.println("JobConsumer - run End");
} -
We wish to connect fat clients (in our case Powerbuilder) to a J2EE environment (Weblogic). We also need to make some of the calls from the fat client non-blocking (asynchronous). With many clients, JMS was rejected as a mechanism.
Our first solution, which works as a prototype, was to package a Java bean as an OLE object and deploy it to the client. This bean could make the calls non-blocking. However there are registry issues (the packaging implies a pre-defined directory structure), we need a JRE on every client and 15Mb of weblogic jars (aaargh), so it only really works as a prototype.
The next (current) solution is a C dll that can be called from Powerbuilder and uses a socket to talk to a Java J2EE Gateway on the server. This Gateway makes the system non-blocking and calls the EJBs. This is clearly easier in terms of configuring the client.
Ideally we would like to drop the Gateway by finding a non-blocking way to get into J2EE from the C dll but the only methods we have thought of:
- simulating an HTTP servlet call
- SOAP
are synchronous (or appear to be, my knowledge of SOAP is limited).
Has anyone come across other ways of getting non-blocking communications with J2EE?CORBA, this is what it was designed to do, but it is not not a light weight solution.
-
I'm trying to learn how to use non-blocking socket channles, but I haven't found much info (nor luck) so far.
To learn, I'm building a server and a client. The server accepts input from the clients and process it in only one thread. The clients should send Objects to the server, and the server process them and return the result also as an Object. For this, I'm trying to use ObjectOutputStream and ObjectInputStream.
The problem I don't know how to solve is that the SocketChannel is in non-bolcking mode, so I can't use their input/output streams (I get a IllegalBlockingModeException). In the server process loop I can reconfigure the SocketChannel to blocking mode to be able to read the Object, but I can't configure it to non-blocking mode again because I get a CancelledKeyException.
Does anyone know how to work with InputStreams and non-blocking channels? Or where to find more info about it?
Here are the relevant part of the server code:
Set ready = selector.selectedKeys();
Iterator i = ready.iterator();
while (i.hasNext()) {
try {
SelectionKey sk = i.next();
i.remove();
if (sk.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel)sk.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
} else if (sk.isReadable()) {
SocketChannel sc = (SocketChannel)sk.channel();
// PROBLEM: If the channel is in non-blocking mode
// I cannot use InputStreams
sk.cancel();
sc.configureBlocking(true);
// Read the object sent by the client
ObjectInputStream in = new ObjectInputStream(Channels.newInputStream(sc));
Object o = in.readObject();
// PROBLEM: Can't put the channel back to non-blocking mode
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ); // CancelledKeyException
} catch (...){
}In my client, this is working fine:
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
for (int i = 0; i < 30000; i++) {
oos = new ObjectOutputStream(sc.socket().getOutputStream());
oos.writeObject(object);
oos.flush();
ois = new ObjectInputStream(sc.socket().getInputStream());
Object o = ois.readObject();
}But trying to do it like this throws a StreamCorruptedException at the server side.
ObjectOutputStream oos = new ObjectOutputStream(sc.socket().getOutputStream());
ObjectInputStream ois = new ObjectInputStream(sc.socket().getInputStream());
for (int i = 0; i < 30000; i++) {
oos.writeObject(object);
oos.flush();
Object o = ois.readObject();
}Do you know why? -
Please help!!!!! on non blocking io
How can I use non blocking IO on client side? is it possible with BufferedReader(new InputStreamReader) on read????
pl. hjelp me, it's urgetn.. :(
Thanx in advanceFoxyLady No, it's Client/Server environment
-
Non-blocking socket concurrent limitation?
I have 2 socket program,one is server side used nio package with JDK1.4.1,the other is client used traditional socket,the client will initialize about 50
threads trying to connect with server when starting,but only about 15
can be accepted,these 2 program are runnning in the same computer which
OS is win2000 professional PC.
the followd is these code:
please make a probe with them ,and tell me what's going on?
server:
package nio_select_demo;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
public class Server implements Runnable
// The port we will listen on
private int port;
// A pre-allocated buffer for processing data
private final ByteBuffer buffer = ByteBuffer.allocate( 16384 );
private ByteBuffer resBuf = ByteBuffer.allocate( 128 );
Selector selector;
AddInfo test ;
public Server( int port ) {
this.port = port;
// for (int i=0; i<threadnum; ++i) {
new Thread( this ).start();
test = new AddInfo();
test.start();
public void run() {
try {
// create a ServerSocketChannel
ServerSocketChannel ssc1 = ServerSocketChannel.open();
// ServerSocketChannel ssc2 = ServerSocketChannel.open();
// Set it to non-blocking
ssc1.configureBlocking( false );
// Get the Socket connected to this channel, and bind it
// to the listening port
ServerSocket ss = ssc1.socket();
InetSocketAddress isa = new InetSocketAddress( port );
ss.bind( isa , 60 );
// Create a new Selector for selecting
selector = Selector.open();
// Register the ServerSocketChannel, so we can
// listen for incoming connections
ssc1.register( selector, SelectionKey.OP_ACCEPT );
System.out.println( "Listening on port "+port );
int n = 0;
while (true) {
// See if we've had any activity -- either
// an incoming connection, or incoming data on an
// existing connection
int num = selector.select();
// If we don't have any activity, loop around and wait
// again
if (num == 0) {
continue;
// Get the keys corresponding to the activity
// that has been detected, and process them
// one by one
Set keys = selector.selectedKeys();
Iterator it = keys.iterator();
while (it.hasNext()) {
// Get a key representing one of bits of I/O
// activity
SelectionKey key = (SelectionKey)it.next();
// What kind of activity is it?
if ((key.readyOps() & SelectionKey.OP_ACCEPT) ==
SelectionKey.OP_ACCEPT) {
System.out.println( "accept request" );
// It's an incoming connection.
// Register this socket with the Selector
// so we can listen for input on it
SocketChannel sc = ((ServerSocketChannel)key.channel()).accept();
System.out.println( "Got connection from "+sc.socket());
// Make sure to make it non-blocking, so we can
// use a selector on it.
//SocketChannel sc = s.getChannel();
sc.configureBlocking( false );
// Register it with the selector, for reading
sc.register( selector, SelectionKey.OP_READ| SelectionKey.OP_WRITE);
} else if ((key.readyOps() & SelectionKey.OP_READ) ==
SelectionKey.OP_READ) {
//ssc.register(selector , SelectionKey.OP_READ);
SocketChannel sc = null;
try {
// It's incoming data on a connection, so
// process it
sc = (SocketChannel)key.channel();
Socket s1 = sc.socket();
s1.setTcpNoDelay(true);
System.out.println( "enter processing data" );
boolean ok = processInput( key );
synchronized (selector) {
key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
// If the connection is dead, then remove it
// from the selector and close it
if (!ok) {
key.cancel();
System.out.println("dead");
Socket s = null;
try {
s = sc.socket();
s.close();
} catch( IOException ie ) {
System.err.println( "Error closing socket "+s+": "+ie );
} catch( IOException ie ) {
ie.printStackTrace();
// On exception, remove this channel from the selector
key.cancel();
System.err.println( "Error raised in this socket");
try {
sc.close();
} catch( IOException ie2 ) { System.out.println( ie2 ); }
System.out.println( "Closed "+sc );
else if ((key.readyOps() & SelectionKey.OP_WRITE) ==
SelectionKey.OP_WRITE) {
System.out.println("Enter Writing");
String response = new String();
if((response=this.test.getInfo())!=null){
resBuf.clear();
SocketChannel sc = (SocketChannel)key.channel();
resBuf = ByteBuffer.wrap( response.getBytes("ISO-8859-1" ) );
sc.write( resBuf );
synchronized (selector) {
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
// We remove the selected keys, because we've dealt
// with them.
keys.clear();
} catch( IOException ie ) {
System.err.println( ie );
private boolean processInput( SelectionKey key ) throws IOException {
buffer.clear();
SocketChannel sc = (SocketChannel)key.channel();
sc.read( buffer );
buffer.flip();
String response = new String("response ok");
// If no data, close the connection
if (buffer.limit()==0) {
return false;
Charset charset=Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
System.out.println(charBuffer.toString());
System.out.println( "Processed "+buffer.limit()+" from "+sc );
return true;
static public void main( String args[] ) throws Exception {
int port = Integer.parseInt( args[0] );
System.out.println(port);
new Server( port );
cilent:
import java.io.*;
import java.net.*;
import java.util.*;
public class Client implements Runnable
private String host;
private int port;
private int acport;
//the size of buffer on how much we write and read per cycle
private static final int maxWriteSize = 128;
public Client( String host, int port, int numThreads ) {
this.host = host;
this.port = port;
for(int i =0;i<50;i++){//initialize 50 client threads
new Thread(this).start();
public void run() {
byte buffer[] = new byte[maxWriteSize];
byte buffer2[] = new byte[maxWriteSize];
try {
Socket s = new Socket( );
InetSocketAddress sa = new InetSocketAddress(host,this.port);
s.connect(sa);
System.out.println(s);
s.setTcpNoDelay(true);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
for (int i=0; i<maxWriteSize; ++i) {
buffer[i] = (byte)'a';
out.write( buffer, 0, maxWriteSize );
int pause = 500;
in.read( buffer , 0 , maxWriteSize );
System.out.println( Thread.currentThread()+" wrote "+maxWriteSize);
String res = new String ( buffer );
String res2 = new String ( buffer2 );
System.out.println( res );
try { Thread.sleep( pause ); } catch( InterruptedException ie ) {}
} catch( Exception ie ) {
ie.printStackTrace();
System.err.println(ie.getMessage());
static public void main( String args[] ) throws Exception {
String host = "127.0.0.1";
int port = Integer.parseInt( args[0] );
int numThreads = Integer.parseInt( args[1] );
new Client( host, port, numThreads );I have found the reason!!!
because of system resource limitation,windows can't afford to maintain
so many concurrent stream-IO,so some socket will be closed.
I modified the client side code,adding thes segments to client instantialize
such as :
public Client( String host, int port, int numThreads ) {
for(int i =0;i<1000;i++){
new Thread(this).start();
try {
Thread.currentThread().sleep(100);//give system some idle
} catch (InterruptedException e) {
/* ignore */
then the server can accept more than 1000 client request concurrently. -
Non-Blocking I/O Implementation Issue
Hi All,
I am trying out the latest JDK 1.4 java.nio.* package. I modified the NBTimeServer and wrote a client which connects to the NBTimeServer and tries to pass messages to and fro. I always succeed to pass on roundtrip of msgs and then Server blocks my client forever. I have modified NBTimeServer to accomodate one client only. Any help or comments on this would be really appreciated. Code is below. Feel free to try it out if want to see what I am trying to convey in this message.
/*******Server Code*******/
Modified this code to test mulitple to and fro msgs between client and server.
Only one client will ever be able to connect to this server during life of a server.
My point here is to demonstrate the to and fro comm between one client and one server
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;
import java.nio.charset.*;
import java.util.regex.*;
// Listen on a port for connections and write back the current time.
public class NBTimeServer {
private static final int DEFAULT_TIME_PORT = 8900;
// Constructor with no arguments creates a time server on default port.
public NBTimeServer() throws Exception {
acceptConnections(this.DEFAULT_TIME_PORT);
// Constructor with port argument creates a time server on specified port.
public NBTimeServer(int port) throws Exception {
acceptConnections(port);
// Accept connections for current time. Lazy Exception thrown.
private static void acceptConnections(int port) throws Exception {
// Selector for incoming time requests
Selector acceptSelector = SelectorProvider.provider().openSelector();
Selector rwSelector = SelectorProvider.provider().openSelector();
// Create a new server socket and set to non blocking mode
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
// Bind the server socket to the local host and port
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(lh, port);
ssc.socket().bind(isa);
// Register accepts on the server socket with the selector. This
// step tells the selector that the socket wants to be put on the
// ready list when accept operations occur, so allowing multiplexed
// non-blocking I/O to take place.
SelectionKey acceptKey = ssc.register(acceptSelector,
SelectionKey.OP_ACCEPT);
int keysAdded = 0;
// Here's where everything happens. The select method will
// return when any operations registered above have occurred, the
// thread has been interrupted, etc.
while ((keysAdded = acceptSelector.select()) > 0) {
// Someone is ready for I/O, get the ready keys
Set readyKeys = acceptSelector.selectedKeys();
Iterator i = readyKeys.iterator();
// Walk through the ready keys collection and process date requests.
while (i.hasNext()) {
SelectionKey sk = (SelectionKey)i.next();
i.remove();
// The key indexes into the selector so you
// can retrieve the socket that's ready for I/O
ServerSocketChannel nextReady =
(ServerSocketChannel)sk.channel();
// Accept the date request and send back the date string
Socket s = nextReady.accept();
SocketChannel sc = s.getChannel();
System.out.println("Got client channel..");
sc.configureBlocking(false);
SelectionKey readKey = sc.register(rwSelector,
SelectionKey.OP_READ|SelectionKey.OP_WRITE);
int count = 0;
while(true) {
if((count = rwSelector.select(1000L)) > 0) {
Set readKeys = rwSelector.selectedKeys();
Iterator i1 = readKeys.iterator();
while(i1.hasNext()) {
System.out.println("Loop in Iterator");
SelectionKey sk1 = (SelectionKey)i1.next();
i1.remove();
if(sk1.isReadable()) {
DataInputStream sin = new DataInputStream(new BufferedInputStream(s.getInputStream(), 4096));
System.out.println(sin.readInt());
if(sk1.isWritable()) {
DataOutputStream sout = new DataOutputStream(new BufferedOutputStream(s.getOutputStream(), 4096));
PrintWriter out = new PrintWriter(sout, true);
Date now = new Date();
out.println(now);
// Entry point.
public static void main(String[] args) {
// Parse command line arguments and
// create a new time server (no arguments yet)
try {
NBTimeServer nbt = new NBTimeServer();
} catch(Exception e) {
e.printStackTrace();
/******End Server Code********/
/*****Begin Client Code********/
import java.io.*;
import java.net.*;
import java.util.*;
// Listen on a port for connections and write back the current time.
public class NBTimeClient {
private static final int DEFAULT_TIME_PORT = 8900;
public static void main(String args[]) throws Exception {
InetAddress lh = InetAddress.getLocalHost();
Socket s = new Socket(lh, DEFAULT_TIME_PORT);
DataInputStream din = new DataInputStream(new BufferedInputStream(s.getInputStream(), 4096));
DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(s.getOutputStream(), 4096));
//Read the time
System.out.println(din.readLine());
//send some junk which is read by server
dout.writeInt(1299);
dout.flush();
//read time again -- I never get anything here and I am blocked here...
System.out.println(din.readLine());
//send some junk back to the server
dout.writeInt(1299);
dout.flush();
s.close();
/*******End Client Code**********/
thanks,
XtrimityThe reason it blocks forever is that you need to keep reusing your main select. That is where the non-blocking event will come from. Here is a bit of code that doesn't block forever.
Tim
http://tim.owlmountain.com
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;
import org.apache.log4j.*;
public class NBServer3 {
int _port = 4000;
Selector _selector = null;
ServerSocketChannel _selectableChannel = null;
int _keysAdded = 0;
static Category log =
Category.getInstance(NBServer3.class.getName());
static String QUIT_SERVER = "quit";
public NBServer3() {
public NBServer3( int port ) {
this._port = port;
public void initialize()
throws IOException {
this._selector = SelectorProvider.provider().openSelector();
this._selectableChannel = ServerSocketChannel.open();
this._selectableChannel.configureBlocking(false);
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(lh, this._port );
this._selectableChannel.socket().bind(isa);
public void finalize()
throws IOException {
this._selectableChannel.close();
this._selector.close();
public void acceptConnections()
throws IOException {
Selects a set of keys whose corresponding channels are ready for I/O
operations. This method performs a non-blocking selection operation.
If no channels have become selectable since the previous selection
operation then this method immediately returns zero.
Returns:
The number of keys, possibly zero, whose ready-operation sets
were updated by the selection operation
do {
SelectionKey acceptKey =
this._selectableChannel.register( this._selector,
SelectionKey.OP_ACCEPT );
log.debug( "Acceptor loop..." );
while (( this._keysAdded = acceptKey.selector().select()) > 0 ) {
log.debug( "Selector returned "
+ this._keysAdded + " ready for IO operations" );
Set readyKeys = this._selector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey)i.next();
i.remove();
if ( key.isAcceptable() ) {
ServerSocketChannel nextReady =
(ServerSocketChannel)key.channel();
log.debug( "Processing selection key read="
+ key.isReadable() + " write=" + key.isWritable() +
" accept=" + key.isAcceptable() );
Socket s = nextReady.accept();
s.getChannel().configureBlocking( false );
SelectionKey readKey =
s.getChannel().register( this._selector,
SelectionKey.OP_READ );
readKey.attach( s );
else if ( key.isReadable() ) {
SelectableChannel nextReady =
(SelectableChannel) key.channel();
log.debug( "Processing selection key read="
+ key.isReadable() + " write=" + key.isWritable() +
" accept=" + key.isAcceptable() );
Socket socket = (Socket) key.attachment();
BufferedReader in = new BufferedReader(
new InputStreamReader( socket.getInputStream() ));
String line = null;
if ( (line = in.readLine() ) != null )
log.debug( line );
log.debug( "End acceptor loop..." );
} while ( false ); //FIXIT tim this should be false. justa test
public static void main( String[] args ) {
BasicConfigurator.configure();
NBServer3 nbServer = new NBServer3();
try {
nbServer.initialize();
} catch ( IOException e ) {
e.printStackTrace();
System.exit( -1 );
try {
nbServer.acceptConnections();
catch ( IOException e ) {
e.printStackTrace();
log.error( e ); -
Non-blocking SocketChannel and close - huh?
It looks like closing a socketchannel that is in non-blocking mode can result in a dead drop of the connection, with some bytes that have already been sent and accepted (as in, 'consumed' from the buffer) being completely dropped.
In fact, I'm generally confused: Actual C non-blocking code has a similar setup for 'close' as you can see in SocketChannel's OP_CONNECT behaviour - just because you want to connect the socket doesn't mean it magically happends without blocking. Wait for a ready flag, then try again.
It should work the same way with close (you try to close, but it may not be possible without blocking).
Is this a huge gaping bug that no one quite figured out just yet, or did I miss something? I loathe to turn on linger, as that's just a crapshoot (you never know if it actually gets through. You could run into funny surprises once the server gets a bit busy. I'd rather not) and tends to cause massive leaks on linux, at least according to some google searches.
There seems to be slightly better performance (in that I have always received all data sofar) if I close the socket instead of the channel (socketChannel.socket().close() instead of socketChannel.close()) - but this has been a random attempt at 'making it work', and I can't find any documentation that backs up that this will DEFINITELY not lose any information without letting me know somehow. That still sounds impossible with this approach.Actual C non-blocking code has a similar setup for
'close' as you can see in SocketChannel's
OP_CONNECT behaviour ...No it doesn't. I don't know what you mean by this.
Closing a socket is asynchronous, but it shouldn't lose any data - if the data can be delivered it will be, followed by the FIN. You don't know when it is delivered, and you don't get to hear about any errors such as an RST coming from the other end, say if it decided to close before reading all the data, or if some intermediate router hung you up.
I'm wondering if you are really dealing with all the short write and zero length write possibilities, i.e. whether the data isn't really still in your output buffer. Don't wish to teach you to suck eggs but there are some subtleties here.
Setting a positive linger timeout doesn't really help because Java doesn't tell you if the timeout expired. (I only asked for this about four years ago). You get to wait while any pending data is delivered, but you still have to guess about whether it all went or the timeout expired, and the behaviour after the timeout expires is platform-dependent: some (Windows) issue an RST, others (Unix) keep trying.
Blocking or non-blocking mode shouldn't make any difference to this (except that Linux will block on a positive linger timeout even in non-blocking mode, which is wrong), and whether you close the channel or the socket is immaterial as one calls the other anyway.
The reason why OP_CONNECT is different in blocking/non-blocking modes is that in blocking mode it won't return until the SYN-ACK is received, while in non-blocking mode it just sends the SYN and relies on you calling connect() again (at the C level) to collect the SYN-ACK, or not - this is what finishConnect() tells you.
tends to cause massive leaks on linux, at least
according to some google searchesIt can't, unless you are referring to the Helix client thing, which appears to be just a badly designed C++ class library with, for some reason, its own linger implementation outside the kernel. -
Why non-blocking write would block usually?
I want to know that why my non-blocking socket's write will consume such a long time. sometimes 400ms worst.
and this is my strace result:
19:17:48.886276 write(1306, "\n\365\31:h#\t\7\237\20\3\21\337\36\276\317\6\3023\6\204\223,-\306\30\322\"\f\1\30\0\n"..., 121) = 121 <0.403088>
It use 0.403088 seconds to finish the write, And I am sure of that the fd 1306 is a non-blocking socket.
Another records shows:
19:15:27.949736 write(995, "\n\365'\236UN\24\10\26Y\16\30\373\26\306\240\36\267z\10\20\342\f\17\301&\253\240\2\325\\\314\354"..., 160) = 160 <0.368412>
19:15:28.410003 write(1466, "\n\365't\360`\20\10\20\342&\253\240\36\267z\10\26Y\26\306\240\16\30\373\2\325\\\f\17\301\314\354"..., 194) = 194 <0.199244>
19:15:28.627854 write(1821, "\n\365'\260*s*\f\17\301\16\30\373\10\26Y\10\20\342\26\306\240\2\325\\&\253\240\36\267z\314\354"..., 160) = 160 <0.397758>
19:15:29.029411 write(755, "\n\365'f\356\1\1&\253\240\36\267z\10\26Y\26\306\240\16\30\373\f\17\301\2\325\\\10\20\342\314\354"..., 160) = 160 <0.399817>
19:15:29.440261 write(614, "\n\365'b\345H\6\36\267z&\253\240\10\26Y\2\325\\\26\306\240\10\20\342\f\17\301\16\30\373\314\354"..., 305) = 305 <0.396985>
19:15:29.846446 write(892, "\n\365'\354\2256t\16\30\373\f\17\301\2\325\\\10\20\342\10\26Y&\253\240\26\306\240\36\267z\314\354"..., 160) = 160 <0.399170>
19:15:30.250257 write(515, "\n\365'\376\343\214i\10\20\342\26\306\240\f\17\301&\253\240\10\26Y\2\325\\\36\267z\16\30\373\314\354"..., 231) = 231 <0.398990>
19:15:30.652666 write(262, "\n\365'\274so\6&\253\240\10\26Y\2\325\\\26\306\240\36\267z\16\30\373\f\17\301\10\20\342\314\354"..., 168) = 168 <0.396569>
19:17:46.885289 write(908, "t\213\16\222\0\0\0\0\240@\33L\0\0\3219\0\0\333J\0\0\2218\0\0\2\0|\203\16\222\0"..., 189) = 189 <0.396330>
19:17:47.351419 write(1529, "\n\365\31\352\2\10\252\36\276\317\30\322\"\6\204\223\6\3023\f\1\30\7\237\20\3\21\337,-\306\0\n"..., 128) = 128 <0.293829>
19:17:47.651080 write(683, "\n\365\31~ZG=\30\322\"\6\204\223\7\237\20\36\276\317\6\3023\3\21\337,-\306\f\1\30\0\n"..., 121) = 121 <0.398178>
19:17:48.062419 write(175, "\n\365\31\224H\260\313\f\1\30\6\3023\3\21\337\36\276\317\6\204\223\7\237\20,-\306\30\322\"\0\n"..., 121) = 121 <0.398811>
19:17:48.467481 write(569, "\n\365\31v5]H\3\21\337\30\322\"\f\1\30\6\3023\6\204\223\7\237\20,-\306\36\276\317\0\n"..., 121) = 121 <0.192335>
19:17:48.663023 write(173, "\n\365\31\376\nJ\0\36\276\317,-\306\7\237\20\30\322\"\3\21\337\6\204\223\6\3023\f\1\30\0\n"..., 121) = 121 <0.206703>
19:17:48.886276 write(1306, "\n\365\31:h#\t\7\237\20\3\21\337\36\276\317\6\3023\6\204\223,-\306\30\322\"\f\1\30\0\n"..., 121) = 121 <0.403088>
BTW, This application is for the service of 3-4K client.
And I do want to ask that:
1.Why non-blocking write will make our process lose the CPU ( I think it is blocked ).
2.What our process waiting for? Why not just return EAGAIN?
3.Can we avoid this problem?
Our server's info:
Linux hz172-96 2.6.32-bpo.5-amd64 #1 SMP Mon May 2 11:40:03 UTC 2011 x86_64 GNU/Linux
Looking forward to your answer, Thank you!thank you for your answer.
and i have resolve this ploblem in using the linux kernel 2.6.30, using kernel 2.6.32 before.
but, i don't kown Is there some bug in linux kernel 2.6.32 or for other reason.
Maybe you are looking for
-
Problem in Receiver determination in case of BPM ASNElectronicLabelPost
Hi I am working on AII flexible delivery scenario its a RFID scenario. XI is part of this architecture. In one BPM ASNElectronicLabelPost receiver service is selected based on <b>condition</b>. the condition is ProcessStep=ASNtoAII based on
-
Hotline call in of all over the world
We install a uccx server in china and have only one hotline number,we use xml file to analyze the incoming call time,my question is how the server can make a difference between the different timezone,such as the USA caller and China caller.could anyo
-
WLS 8.1 Type 4 JDBC Driver SQL Server sp_prepare/sp_execute
Hello, I have a question regarding performance troubleshooting in a production situation using the WLS 8.1 Type 4 JDBC Driver for SQL Server and SQL Server 2000. This driver compiles a sql statement on the sql server using sp_prepare(), saving a hand
-
Hi, I need to restrict the access to VA01, VA02, VA03 and VA05 depending on VKBUR and VKGRP. Is it possible? Do I need to modify any user-exit? Thanks in advance, Ricard.
-
I am trying to upload my Adobe muse site from a different project but it will not let me. I started a new project and want to overwrite the webpage but it says the username is incorrect. however on the original project the username was correct.