Solved

Problem with sockets.

Posted on 2001-06-12
9
279 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
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!

 
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: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering 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

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
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…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Suggested Courses
Course of the Month9 days, 7 hours left to enroll

624 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