c# - Gracefully closing a named pipe and disposing of streams -
i have two-way named pipe. i'm not sure how shut down gracefully, though, once i'm done - if close connection client side, server side throws exception when tries dispose of streamreader , streamwriter i'm using. i'm catching it, seems kludge job me.
server side code:
thread pipeserver = new thread(serverthread); pipeserver.start(); private void serverthread(object data) { int threadid = thread.currentthread.managedthreadid; log.debug("spawned thread " + threadid); pipesecurity ps = new pipesecurity(); securityidentifier sid = new securityidentifier(wellknownsidtype.worldsid, null); ps.addaccessrule(new pipeaccessrule(sid, pipeaccessrights.readwrite, system.security.accesscontrol.accesscontroltype.allow)); ps.addaccessrule(new pipeaccessrule(windowsidentity.getcurrent().owner, pipeaccessrights.fullcontrol, system.security.accesscontrol.accesscontroltype.allow)); log.debug("pipe security settings set [thread " + threadid + "]"); namedpipeserverstream pipeserver = new namedpipeserverstream("rdpcommunicationpipe", pipedirection.inout, numthreads, pipetransmissionmode.message, pipeoptions.none, 0x1000, 0x1000, ps); log.debug("pipe servers created"); // wait client connect log.info("pipe created on thread " + threadid + ". listening client connection."); pipeserver.waitforconnection(); log.debug("pipe server connection established [thread " + threadid + "]"); thread nextserver = new thread(serverthread); nextserver.start(); try { // read request client. once client has // written pipe security token available. using (streamreader sr = new streamreader(pipeserver)) { using (streamwriter sw = new streamwriter(pipeserver) { autoflush = true }) { // verify our identity connected client using // string client anticipates. sw.writeline("i 1 true server!"); log.debug("[thread " + threadid + "]" + sr.readline()); log.info(string.format("client connected on thread {0}. client id: {1}", threadid, pipeserver.getimpersonationusername())); while (!sr.endofstream) { log.debug("[thread " + threadid + "]" + sr.readline()); } } } } // catch ioexception raised if pipe broken // or disconnected. catch (ioexception e) { log.error("error: " + e); } }
client side code:
class program { static void main(string[] args) { console.writeline("starting..."); var client = new namedpipeclientstream(".", "rdpcommunicationpipe", pipedirection.inout); client.connect(); console.writeline("pipe connected successfully"); using (streamreader sr = new streamreader(client)) { using (streamwriter sw = new streamwriter(client) { autoflush = true }) { string temp; { temp = sr.readline(); console.writeline(temp); } while (temp.trim() != "i 1 true server!"); sw.writeline("message received , understood"); while (!string.isnullorempty(temp = console.readline())) { sw.writeline(temp); } } } client.close(); } }
it works until hit enter on empty line in client app, terminates it, closing client. server app throws system.io.ioexception: pipe broken.
when hits end of streamwriter using
block. how dispose of stream handlers?
i'm catching it, seems kludge job me.
imho, it's you're going get, if want neighbor , dispose owned streamwriter
object , still invest minimum of effort.
that said, seems me in particular situation, it'd fine comment out call dispose()
— or in case, not use using
statement — , include comment explaining @ point in sequence of execution of code, know call going throw exception, , there's no point in making it.
of course, if don't bother disposing streamwriter
, you'll want explicitly dispose pipe stream. might want use streamwriter
constructor has leaveopen
parameter, , pass true
parameter, way of documenting intent not have streamwriter
own pipe stream object.
either way, you're going wind leaving object in finalizer queue, because exception bypasses call gc.suppressfinalize()
, (of course) not bothering call dispose()
@ all. long aren't dealing high-volume scenario (i.e. lots of these objects), that's fine. it's not ideal.
unfortunately, named pipes don't have semantics provide kind of "graceful closure" sockets do. is, way endpoint indicate done writing disconnect (for server pipe) or close (for server or client pipes). neither option leaves pipe available reading, implementing graceful closure on pipe requires handshaking within application protocol itself, rather relying on i/o object .
in addition inconvenience (which admit, isn't directly related question), implementation of pipestream.flush()
checks see whether pipe writeable. even though has no intention of writing anything! it's last part find annoying, , of course directly causes issue you're asking about. seems unreasonable me code in .net framework go out of way throw exceptions in scenarios exceptions cause more trouble good.
all said, have other options:
- subclass
namedpipeserverstream
,namedpipeclientstream
types, , overrideflush()
method nothing. or rather, nice if this. typessealed
, can't. - alternative subclassing types, can wrap them in own
stream
implementation. lot more of hassle, since going want override of async members, @ least if intend use these objects in situation i/o performance of interest. - use separate one-directional pipes reading , writing. in implementation, can close
streamwriter
way of closing connection, results in correct order of things (i.e. flush happens before close on pipe). addresses graceful closure issue, because 2 pipes each connection, can have same basic "half-closed" semantics sockets have. of course, option complicated challenge in identifying pairs of pipe connections go each other.
both of these (that is, second , third ones, i.e. ones possible) have obvious drawbacks. having have own stream
class pain, due duplication of code required. , doubling pipe object count seems drastic way address exception (but acceptable , desirable implementation support graceful closure semantics, happy side-effect of eliminating thrown-exception issue streamwriter.dispose()
).
note in high-volume scenario (but then, why using pipes? 😊 ), throwing , catching exceptions high frequency problem (they expensive). 1 or other of these 2 alternative options preferable in case, on either catching exception , not bothering close/dispose streamwriter
(both of add inefficiencies interfere high-volume scenario).
Comments
Post a Comment