SRL Archive - Senior Scripts and Snippets

TCP Chat


Smartzkid

2007-06-29 20:23:44

*hopes that this section isn't limited to RS pieces*

Well, today I created a TCP Chat program. It uses TCP to communicate with the server (my laptop). The only problem is that the server I'm using (Net Tools -> Net Tools Mini -> TCP Server) will only allow 1 on 1 communication. If anyone here has delphi experience, I would love some help developing a simple 'chat server' that:
  • Auto-Resets connection problems that result when SCAR doesn't close a connection
  • takes all incoming data and puts it into one group (allowing all connected parties to chat with eachoter)
  • can block ip's
  • can run off any port

Of course, it doesn't have to be in delphi, it could be in java, C, even assembly, just then, instead of it being you helping me, it'd be you making the whole server for me…

Well, here's my code…


program TCPChat;
var
frmDesign : TForm;
Edit1 : TEdit;
MessageBox : TRichEdit;
SendBox : TEdit;
Send : TButton;
TCP_conn_index: integer;

procedure TCP_close; forward;

procedure SendMessage(Sender: TObject);
begin
SendConnectionData(TCP_conn_index, Edit1.Text + ': ' + SendBox.Text);
MessageBox.Lines.Add(Edit1.Text + ': ' + SendBox.Text);
if(MessageBox.Lines.Count > 13)then
MessageBox.Lines.Delete(1);
SendBox.Text := '';
end;

procedure ResizeElements(Sender: TObject);
begin
if(frmDesign.Width < 200)then
frmDesign.Width := 200;
if(frmDesign.Height < 160)then
frmDesign.Height := 160;
MessageBox.Width := frmDesign.Width - 10;
MessageBox.Height := frmDesign.Height - 85;
Send.Left := frmDesign.Width - 67;
Send.Top := frmDesign.Height - 59;
SendBox.Width := frmDesign.Width - 69;
SendBox.Top := frmDesign.Height - 59;
end;

procedure InitForm;
begin
frmDesign := CreateForm;
frmDesign.Left := 250;
frmDesign.Top := 114;
frmDesign.Width := 280;
frmDesign.Height := 259;
frmDesign.Caption := 'TCP Chat';
frmDesign.Color := clBtnFace;
frmDesign.Font.Color := clWindowText;
frmDesign.Font.Height := -11;
frmDesign.Font.Name := 'MS Sans Serif';
frmDesign.Font.Style := [];
frmDesign.Visible := True;
frmDesign.PixelsPerInch := 96;
frmDesign.Onresize := @ResizeElements;
Edit1 := TEdit.Create(frmDesign);
Edit1.Parent := frmDesign;
Edit1.Left := 1;
Edit1.Top := 1;
Edit1.Width := 130;
Edit1.Height := 21;
Edit1.TabOrder := 8;
Edit1.Text := 'Nickname';
MessageBox := TRichEdit.Create(frmDesign);
MessageBox.Parent := frmDesign;
MessageBox.Left := 1;
MessageBox.Top := 24;
MessageBox.Width := 270;
MessageBox.Height := 174;
MessageBox.HideSelection := False;
MessageBox.HideScrollBars := False;
MessageBox.Lines.Add('Welcome to TCP Chat client provided by Smartzkid!');
MessageBox.WordWrap
MessageBox.TabOrder := 9;
SendBox := TEdit.Create(frmDesign);
SendBox.Parent := frmDesign;
SendBox.Left := 1;
SendBox.Top := 200;
SendBox.Width := 211;
SendBox.Height := 21;
SendBox.TabOrder := 10;
Send := TButton.Create(frmDesign);
Send.Parent := frmDesign;
Send.Left := 213;
Send.Top := 200;
Send.Width := 57;
Send.Height := 22;
Send.Caption := 'Send';
Send.TabOrder := 11;
Send.OnClick := @SendMessage;
end;

procedure SafeInitForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitForm', v);
end;

procedure ShowForm;
begin
frmDesign.SHOW;
end;

procedure SafeShowForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('ShowForm', v);
end;

procedure Form;
begin
SafeInitForm;
SafeShowForm;
end;

function TCP_connect: Boolean;
begin
if (TCP_conn_index <> 0) then FreeConnection(TCP_conn_index);
TCP_conn_index := OpenConnection('68.80.192.208', 5990, 300);
end;

procedure TCP_close;
begin
if(TCP_conn_index <> 0)then
FreeConnection(TCP_conn_index);
TCP_conn_index := 0;
end;

procedure TCP_listen;
var
str: string;
begin
if(ReadConnectionData(TCP_conn_index, str))then
MessageBox.Text := MessageBox.Text + str;
if(MessageBox.Lines.Count > 13)then
MessageBox.Lines.Delete(1);
end;

begin
try
TCP_connect;
Form;
repeat
TCP_listen;
wait(5);
until(not(frmDesign.Showing))
finally
SendConnectionData(TCP_conn_index, 'Please close');
TCP_close;
frmDesign.ModalResult := 1;
FreeForm(frmDesign);
end;
end.

For now, I only released this here because I don't want to be flooded with connections, I know someone would hit [ctrl] [alt] and screw everything up, and it has yet to develop into a group chat program.

EDIT: Before anyone complains, yes, I did use [part of] kyab.scar's connect and close procedures

UPDATE: Fixed the scrolling bug (temporarily)

SERVER STATUS: NOT RUNNING (busy with school + rewriting a script or two; if you really want to try it, hit me up on msn)

Ron

2007-07-01 08:25:40

I would like to try, but I am unable to because I'm not allowed to install anything on this computer. But I will nag you that you didn't free your form! :p

FreeForm(frmDesign); // Frees the form from memory!

and instead of having

frmDesign.HIDE;

change that to this:

frmDesign.ModalResult := 1; // Kills the Form Window.
FreeForm(frmDesign); // Frees the form from memory!

Also you can resize your form and your components do not resize with it! I suggest adding this code so things will look the way you want your form to look.

frmDesign.BorderIcons := [biSystemMenu, biMinimize]; // Disables Maximize.
frmDesign.BorderStyle := bsSingle; // Disables resizing.

Other than that I hope to try your script. I'm sure it will be really sweet. But I would also like to say that you do not need a TCP server just to process this. You could just use SCAR with some server script (like PHP) and do it that way. First make the chat on a website then use scar to process it using GetPage and then by manipulating the HTML. That way your chat won't be 1 on 1, it will be like a chat room.

~Ron :)

Smartzkid

2007-07-01 16:53:47

Thanks a ton for the input, Ron.

I made the form resizing work (:p was too lazy to do it before), freed and closed the form correctly, and fixed a couple other annoyances I'd come across

Awesome idea with the php, I think I'll try it (later though, competition script is still keeping me busy)

Dark_Sniper

2007-07-02 02:00:27

lol i made one of these… but never got it to work XD

gj im checking this out..

Freddy1990

2007-07-06 19:27:09

Heh, I'd write a server, but I'm too lazy :P
Anyway, got a few tips though…

1. Make the server send a greet and make the client check for that. That basically means that the server sends a message upon connecting to the client. Useful to check if ur rly connected to the (right) server.

2. Set the username before chatting, not during. Send it to the server so it can couple it to the user's ip.

3. Allow users to mute people.

4. Add the ability to keep a chatlog. (Logs should also be kept by the server for sure, connectionlogs, chatlogs, etc…)

5. Build in support for basic servercommands besides just messages.

Ejjman

2007-08-03 02:35:14

Just a thought, in the futuer, make a drawing game. It'd be really advanced but….



U make a celint, for poelpe to draw on, one person draws and gets a random word from a lsit we make and u draw it the first person that says that word in CaPs DoNT mATtER then the person who is correct draws.

Haha.

That would be awesome!

moparisthebest

2007-09-07 17:00:46

It would be easy to write the server in java, and it would also run on any platform, do you have the protocol written up yet?

Smartzkid

2007-09-07 23:27:15

I'm pretty busy nowadays, so…no.

A protocol is just a way to define different commands, right?

Server Sends: [mpub]A Message.
Client displays 'A Message' in the public chat area

I'll read up on protocols a bit more tomorrow.

I guess I might start re-learning Java…just haven't exactly felt inclined to start writing java code because I really don't see a use for it (not now, atleast)

moparisthebest

2007-09-08 03:45:27

That is pretty much protocol. For example with HTTP (a protocol) the client sends 'GET /somefile/' and then the server responds with the file.