Solved

Problem with sockets.

Posted on 2001-06-12
9
277 Views
Last Modified: 2010-04-06
Ok, I'm new to the whole socket programming thing, so I probably just have some bad code. Basically I need someone to figure out the bad parts of this code, basically, if you can't see what I'm trying to do here, you have no buisiness helping me. Blunt but honest, sorry.

Here'a a large portion of my source there are some things here that don't have any releavance but here they are anyways... Basically what I want to do is send these numeric commands to the client and server... I have written a beginning to the procedure that is supposed to parse them, but when I stop on the code that reads the socket, it just says "()" which I guess means nil, I dunno if I'm using the wrong method here or what. But basically I don't want to have to limit the amount of users that can connect so this is not a client/server only I have in mind here... the person that hosts connects to their own server upon doing so, and everything is handled that way (or is supposed to be) I hope someone can make sense of this code cause I don't know where I'm going wrong.

Thanks,

Psylord


procedure TForm1.FormShow(Sender: TObject);
begin
MyNickName := 'Psylord';
end;

procedure TForm1.Echo(Content: String);
begin
Memo1.Lines.Add(Content);
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin

if key = #13 then
 begin
  key := #0; {Ditch the beep}
  if not Connected then
   begin
    Echo('*Not Connected');
   end;
 {We're Connected, Send the command:}
//Not implemented yet
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Users := TStringList.Create;
end;

procedure TForm1.JoinServer(Host: String; Port: Integer);
begin
{Here's where we connect}
Client.Port := Port;
Client.Host := Host;
Client.Active := True;
end;

procedure TForm1.BeginHost(Port: Integer);
begin
{Let's start the server}
Server.Port := Port;
Server.Active := True;
Application.ProcessMessages;
{We need to join our own server now}
JoinServer('localhost', ServerPort);
end;

procedure TForm1.ServerClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
Echo('*Connection request: ' + Socket.RemoteAddress + ':' + IntToStr(Socket.LocalPort) + ' requesting authentication.');
end;

procedure TForm1.ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Connected := True; {We're Connected to the server}
Echo('*Connected to server: ' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort) + ' sending authentication.');
SendToServer(100, MyNickName, Socket);
end;

procedure TForm1.ServerClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
    Line: string;
    I: Integer;
    FReceiveBuffer: String;
begin
 FReceiveBuffer:=FReceiveBuffer+Socket.ReceiveText;
 I:=Pos(#13,FReceiveBuffer);
 while I>0 do begin
  Line:=Copy(FReceiveBuffer,1,I-1);
  Delete(FReceiveBuffer,1,I);
  Line:=StringReplace(StringReplace(Line,'\n',#13,[rfReplaceAll]),'\\','\',[rfReplaceAll]);
  I:=Pos(' ',Line);
  ParseCommand(Socket, StrToInt(Copy(Line,1,I-1)), Copy(Line, I+1, Length(Line)));
  I:=Pos(#13,FReceiveBuffer);
 end;

end;

procedure TForm1.ParseCommand(Socket: TCustomWinSocket; Numeric: Integer; Content: String);
begin

 case Numeric of
  100:
   begin
   Echo('*Debug: 100 recvd');
    {The numeric was "100"!}
{    Client.Socket.SendText(IntToStr(Numeric) + ' ' + Content);
    Server.Socket.SendText(IntToStr(Numeric) + ' ' + Content);}
   end;

 end; {Case}

end; {Proc}

procedure TForm1.SendToServer(Numeric: Integer; Content: String; Socket: TCustomWinSocket);
begin
Socket.SendText(Format('%d %s',[Numeric,StringReplace(StringReplace(Content,'\','\\',[rfReplaceAll]),#13,'\n',[rfReplaceAll])]));
end;

procedure TForm1.SendToClient(Numeric: Integer; Content: String; Socket: TCustomWinSocket);
begin
Socket.SendText(Format('%d %s',[Numeric,StringReplace(StringReplace(Content,'\','\\',[rfReplaceAll]),#13,'\n',[rfReplaceAll])]));
end;

procedure TForm1.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
    Line: string;
    I: Integer;
    FReceiveBuffer: String;
begin
 FReceiveBuffer:=FReceiveBuffer+Socket.ReceiveText;
 I:=Pos(#13,FReceiveBuffer);
 while I>0 do begin
  Line:=Copy(FReceiveBuffer,1,I-1);
  Delete(FReceiveBuffer,1,I);
  Line:=StringReplace(StringReplace(Line,'\n',#13,[rfReplaceAll]),'\\','\',[rfReplaceAll]);
  I:=Pos(' ',Line);
  ParseCommand(Socket, StrToInt(Copy(Line,1,I-1)), Copy(Line, I+1, Length(Line)));
  I:=Pos(#13,FReceiveBuffer);
 end;
end;


If this can be fixed the way I want it to be, that would rock heavy metal style!! *Dances upside down*


I do low points cause I'm getting low and this should be easy to any socks expert. Sorry.
0
Comment
Question by:Psylord
9 Comments
 
LVL 12

Expert Comment

by:rwilson032697
ID: 6184768
When you say "... is just says '()', I guess that means nil...' you mean when you inspect its value via a tool tip?

Delphi usually does this if it can't determine the class of the item being pointed eg (eg: it is the 'sender' which is usually TObject...). It does not mean thats its value is nil, otherwise the tooltip would have said so.

You can examine its values by casting the item in the watch window (eg: TMyObject(Sender) )

Cheers,

Raymond.
0
 

Author Comment

by:Psylord
ID: 6185171
Yeah ok. That's what I meant, when I put a breakpoint onit it did what you just said. I still don't know what I'm doing wrong though. The data just isn't being handled correctly and I dunno what else to do. :(
0
 
LVL 4

Expert Comment

by:Colin_Dawson
ID: 6185393
I've not looked at the code in detail, But I can see that you're using the TClientSocket & TServerSocket.  I tried to use this and found them quite complicated.  Just a thought, but have you considered using the INDY components (a.k.a WinShoes).  They're open source and also part of Kylix and Delphi 6.  You can download them free from

http://www.nevrona.com/Indy/

Regards

Colin Dawson
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Expert Comment

by:edsteele
ID: 6187812
Could you post a listing of the output when you run this?  That would help me.  Also, in the following code:

procedure TForm1.BeginHost(Port: Integer);
begin
{Let's start the server}
Server.Port := Port;
Server.Active := True;
Application.ProcessMessages;
{We need to join our own server now}
JoinServer('localhost', ServerPort);
end;

Where are you getting "ServerPort" in the last line?  Should that be "Server.Port"?

Eric
0
 

Author Comment

by:Psylord
ID: 6188082
Colin, I tried indy and it gave me an error when I started Delphi.

Eric,

You're right ServerPort should actually be changed to "Port"

There is no output generated, so I can't give any to you... There are no errors in the actual code, but then on the other hand, it's not getting the data for some reason.

0
 
LVL 1

Expert Comment

by:edsteele
ID: 6188134
No output?  But, you have a call to "Echo" in both connect methods.  This seems to tell me that you are not getting a connection at all.

Why don't you try adding some calls to "echo" in your problem spots and look at data that way.  I would place one at the beginning and end of each method you use, then place another in every location something significant happens.  This should give a very nice "trace" of the program execution.  If you can post that, then we can really help you.

Eric
0
 

Author Comment

by:Psylord
ID: 6188301
My echo is just there as one of the non relevant procedures I mentioned above. It is connecting, because my onconnect events are being triggered ok.

In my connect event for my Client socket, I try to send a numeric to the server, that's where the problem must be, it doesn't seem to be sending right.

0
 
LVL 1

Accepted Solution

by:
edsteele earned 150 total points
ID: 6191451
The echo may be non-relevant, but it can be invaluable for debugging purposes.

Anyway, I found your problem.  The problem isn't in the code as much as in the data you are passing to the sockets.  I pasted the code you supplied into a new project and sprinkled it with Echo statements.  The ServerClientRead is being executed, but it is not finding anything (Well, your code isn't finding anything, ServerClientRead did get the string).  The problem is your use of the #13 character.  When you sent your nickname to the server, there was no #13 behind it, so your code in ServerClientRead thinks there is nothing to look at.

My solution is to replace the #13 with #182(the paragraph symbol).  Also change the code in SendToServer and SendToClient to do something like:

  Socket.SendText(Format('%d %s'#182,[Numeric,StringReplace(StringReplace(Content,'\','\\',[rfReplaceAll]),#13,'\n',[rfReplaceAll])]));

You may be able to shorten that StringReplace stuff now, since the #13 will not be needed.

When I made these changes, it found your nickname and I got the proper response from the ParseCommand procedure.

Enjoy!
Eric
0
 

Author Comment

by:Psylord
ID: 6192767
Thanks! Works great! Appreciate the help. Increased points by 100. Sorry, all I can spare right now.
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

679 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question