Newsgroups : Borland : borland.public.delphi.internet.winsock : 2005 Aug : Problems with Java socket server and Indy

www.cryer.info
Managed Newsgroup Archive

Problems with Java socket server and Indy

Subject:Problems with Java socket server and Indy
Posted by:"Kari Kupiainen" (karik..@saunalahti.fi)
Date:Tue, 2 Aug 2005 00:14:30

Hi,

Trying to send and receive data between a windows client application and a
socket server written in Java.
The data transfer is supposed to follow a simple protocol. Example of the
messaging format is like this

Messages are passed by writing the following to a TCP/IP socket stream:

  1.. a four byte integer containing the ID of a message
  2.. a four byte integer containing the size of the message data
  3.. the message data itself
The login message is data is specified like this:

String userid the user id the client will play under
String passwd the password for the given userid
int version Protocol Version (1)
String client_name The name of your program (optional)

The implementation of the Java message handler for login message looks like
this:

// Wait for our client to request to join the game - ignore all other
messages.
   while (true) {
    Message M=GetNextMessage();
    if (M.ID==C_JOIN_GAME) {
     SendMessage(new Message(C_GOODPASS)); // Tell the client it can join.
     int Len;
     for (Len=0;Len<M.Data.length;Len++)
      if (M.Data[Len]=='\0')
       break;
     SendMessage(new Message(C_CHATTER,(new
String(Confirm+"\0")).getBytes()));
     Connected=true;    // Have connected successfully.
     break;
    }

The GetNextMessage method is implemented like this:

// This function will read in the next message from the remote client and
return it.
// NOTE: This is a 'blocking' function, and we cannot leave until we
recieve
//       the whole of the message we are expecting.
public Message GetNextMessage() {
  Message M = new Message(ReadInt(),ReadInt());
  for (int I=0;I<M.Data.length;I++) {
   M.Data[I]=(byte)ReadByte();
  }
  return M;
}

The ReadInt is implemented like this:

// This function will read the next 4-byte integer from the remote client
and return it.
// NOTE: This is a 'blocking' function, and we cannot leave until we
recieve
//       the whole of the integer we are expecting.
private int ReadInt() {
  int RetVal=0;
  for (int I=3;I>=0;I--)
   RetVal|=((int)ReadByte())<<(I*8);
  return RetVal;  // High order first???
}

and the ReadByte like this:

private byte ReadByte() {
  int ByteRead=-1;
  while (ByteRead==-1) {
   try {
    ByteRead=InStream.read();
   }
   catch (IOException e) {
    try{
     Thread.sleep(getDelayMS());
    }
    catch ( InterruptedException e2) {}
     ByteRead=-1;
   }
  }
  return (byte)ByteRead;
}

So it should be plain simple to send a login message to the server. My
implementation of the client sending the login message is like this:

procedure TfMain.SendMessage(Msg : TPokerMsg);
begin
  // The connection is opened before this
  WriteInt(Msg.Msg);     // Write the message identifier. Msg.Msg = 20 ->
JOIN_GAME
  WriteInt(Msg.DataSize);   // Write the size of the data
  try
    // Write the data itself
    TCPClient.WriteBuffer(JoinGame,Msg.DataSize,False); // Don't send
immediately
    TCPClient.FlushWriteBuffer(Msg.DataSize);           // Send and clear
buffer
  except
   //
   on E: Exception do ShowMessage(E.Message);
  end;
end;

JoinGame is a packed record according to the protocol-> this is the data to
be sent.

userid : PChar;         // the user id the client will play under
passwd : PChar;         // the password for the given userid
version : integer;      // Protocol Version (1)
client_name : PChar;    // The name of your program (optional)

Msg.Msg is the ID of the message (integer) and Msg.DataSize (integer) is the
size of the data to be sent = JoinData.
WriteInt looks like this:

procedure TfMain.WriteInt(n : integer);
var i : integer;
    c : byte;
begin
  //
  try
    //
    for i := 3 downto 0 do
     begin
      c := Byte(n shr (i * 8));
      TCPClient.WriteBuffer(c,SizeOf(c),False);     // Write one byte a time
      TCPClient.FlushWriteBuffer(SizeOf(c));
     end;
  except
   //
   on E: Exception do ShowMessage(E.Message);
  end;
end;

The TCPClient is the TCP client in Indy 9. When I connect to the socket it
connects fine but when the
first WriteInt procedure is invoked the connection closes gracefully
indicating that the server has intensionally closed the connection ???
Every attemp using the Writebuffer method leads to the same exception. The
Java code is not mine and I cannot make modifications in it.

Any help much appreciated !

Regards Welho

Replies:

www.cryer.info
Managed Newsgroup Archive