Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 282
  • Last Modified:

Problem with sockets.

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
Psylord
Asked:
Psylord
1 Solution
 
rwilson032697Commented:
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
 
PsylordAuthor Commented:
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
 
Colin_DawsonCommented:
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
Independent Software Vendors: 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!

 
edsteeleCommented:
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
 
PsylordAuthor Commented:
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
 
edsteeleCommented:
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
 
PsylordAuthor Commented:
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
 
edsteeleCommented:
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
 
PsylordAuthor Commented:
Thanks! Works great! Appreciate the help. Increased points by 100. Sorry, all I can spare right now.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now