From: Robert Klemme Date: 2012-08-20T20:08:03+09:00 Subject: Re: TCPserver how to signal EOT On Mon, Aug 20, 2012 at 11:57 AM, tammy roberts2 wrote: > Hi Robert, it is me again, my computer crashed and I lost my login > information. Here is what I am using right now, it seems to be working > fine, but maybe you see problems with it or a way to improve. Also maybe > it will help someone else out who is struggling with the same problem I > was. This is a completely different approach: you do not use a termination byte any more but transmit the message length beforehand. > > class Networking > > def initialize > @settings = Settings.new > end > > def listen(server) > loop do > Thread.start(server.accept) do |client| > data_received = [] > total_received = 0 > incoming_data_size = client.recvfrom( 4 )[0].unpack('N*')[0] > > loop do > section_size = client.recvfrom( 4 )[0].unpack('N*')[0] > message_section = "" > > loop do > message_section << client.recvfrom( section_size )[0] > break if message_section.bytesize == section_size > end > > data_received << message_section > total_received += 4 + message_section.bytesize > break if total_received == incoming_data_size > end > > yield(data_received, client) > end > end > end > > def send_data(socket, message) > forward_message = [message.bytesize].pack('N*') + message > socket.send(forward_message, 0) > yield(socket) > end Why do you yield the socket? > def get_reply(socket) > incoming_data_size = socket.recvfrom( 4 )[0].unpack('N*')[0] > section_size = socket.recvfrom( 4 )[0].unpack('N*')[0] > reply = "" > > loop do > reply << socket.recvfrom( section_size )[0] > break if reply.bytesize == incoming_data_size - 4 > end > > yield(reply, socket) > end > end If you use #send then I'd also use #read for reading instead of #recvfrom. I'd only use that method if I needed the extra options. Method #read will also block until as many bytes have arrived so you do not take care of fragment messages yourself. I'd probably choose a tad different approach by wrapping the connection with something that does the message handling and creation of a message type (for specific parsing etc.): # could be more sophisticated Message = Struct.new :bytes Connection = Struct.new :socket do def send(msg) b = msg.bytes socket.write [b.bytesize].pack 'N' socket.write b self end def close socket.close end def each_msg until socket.eof? size = socket.read(4).unpack('N').first msg = socket.read(size) yield Message.new(msg) end end self end end loop do Thread.new(server.accept) do |client| conn = Connection.new client conn.each_msg do |msg| yield msg, conn end end end Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/