Q&A

  • 간단한 채팅프로그램인데요.
단순한  채팅프로그램인데요.

한 프로그램상에 서버와 클라이언트가 모두 구현되어 있습니다.

프로그램을 실행시켜서 서버 모드로 실행하게 하고

프로그램을 하나 더 띄워서 클라이언트 모드로 실행하게 합니다.

그후에 클라이언트에서 서버로 접속후

클라이언트에서 글을쓰면 정상적으로 서버로 전송이 되는데

문제는...

서버에서 글을 쓰면

서버가 다운이 되버리네요.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, ExtCtrls,
  StdCtrls, IdTCPServer, IdContext;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    Edit2: TEdit;
    Edit3: TEdit;
    Timer1: TTimer;
    IdTCPClient1: TIdTCPClient;
    IdTCPServer1: TIdTCPServer;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure Timer1Timer(Sender: TObject);
    procedure Edit3KeyPress(Sender: TObject; var Key: Char);
    procedure IdTCPClient1Disconnected(Sender: TObject);
    procedure IdTCPClient1Connected(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if IdTCPClient1.Connected then
  begin
    IdTCPClient1.Disconnect;
    Button1.Caption:='Connect';
  end
  else
  begin
    IdTCPClient1.Host:=Edit1.Text;
    IdTCPClient1.Port:=2010;
    IdTCPClient1.Connect;
    Button1.Caption:='Disconnect';
  end;
end;

procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
  Memo1.Lines.Add('Connection to '+Edit1.Text+' is complete');
end;

procedure TForm1.IdTCPClient1Disconnected(Sender: TObject);
begin
  Memo1.Lines.Add('Disconnection to '+Edit1.Text+' is complete');
end;

procedure TForm1.Edit3KeyPress(Sender: TObject; var Key: Char);
var
i:integer;
begin
  if Key = #13 then // 엔터키가 눌러졌을 경우
  begin
    if IdTCPClient1.Connected then // 클라이언트 일경우
    begin
      // 소켓에 ID와 글의 내용을 한 문자열로 만든후 쓴다.
      IdTCPClient1.Socket.WriteLn(Edit2.Text+' : '+Edit3.Text);
    end
    else // 서버 일경우
    begin
      // 자신의 메모창에 쓴 글의 내용을 ID와 함께 출력한다.
      Memo1.Lines.Add(Edit2.Text+' : '+Edit3.Text);
      try
        // 루프를 돌면서 서버에 접속되어있는 모든 클라이언트들에게 메세지를 전송한다.
        for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do <== 이 부분에서 멈추더군요
          // 서버에 접속되어 있는 i번째 쓰레드의 소켓에 글의 내용과 ID를 한 문자열로 해서 쓴다.
          TIdContext(IdTCPServer1.Contexts.LockList.Items[i]).Connection.Socket.WriteLn(Edit2.Text + ' : ' + Edit3.Text);
      finally
        IdTCPServer1.Contexts.UnlockList; // threads list 자원을 해제해준다.
      end;
    end;
    Edit3.Clear; // 다음 내용을 입력받기 위해서 Edit3 창을 클리어 시켜준다.
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
rcv:string;
begin
  if IdTCPClient1.Connected then // 클라이언트 모드일경우
  begin
    rcv:=IdTCPClient1.Socket.ReadLn('',10); // 소켓에서 받은 내용을 읽어와 rcv에 담는다.
    if rcv <> '' then // 빈 문자열이 아닐경우에만
      Memo1.Lines.Add(rcv); // rcv 내용을 Memo1에 출력한다.
  end
end;


procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
rcv:string;
i:integer;
begin
  try
  rcv:= AContext.Connection.Socket.Readln('',10);
  if rcv<>'' then
  Memo1.Lines.Add(rcv);
  try
  for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do
   TIdContext(IdTCPServer1.Contexts.LockList.Items[i]).Connection.Socket.WriteLn(rcv);
  finally
   IdTCPServer1.Contexts.UnlockList;
  end;
  except
   AContext.connection.disconnect;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Button1.Enabled:=false;
  Button2.Enabled:=false;
  IdTCPServer1.Active:=true;
end;

end.

흑 어렵네요 ㅡㅡ;;;
0  COMMENTS