Sockety (problem) przy wysyłaniu tekstu.

0

Witam,

Siedzę już nad tym xxx godzin i nie mogę wyczaić co robie źle.

Program to serwer czatu, wysyłamy do niego wiadomość a on rozsyła ją wszystkim klientom.

Brzmi bardzo prosto, w praktyce też jest proste tyle że nie działa.

Objawy:
Gdy zalogowany jest tylko jeden klient, serwer sprawuje się doskonale.
po dołączeniu drugiego klienta, serwer wysypuje takim komunikatem:

user image

var
List: TStringList;
	k:integer;
	i,ii,iii,iiii:integer;
	idMessage : TIdMessage;
    s,b,wiadomosc:string;
    zmienna3:pchar;
         sprawdzanieloginu,sprawdzaniehasla:integer;
begin
	for ii:=0 to ServerSocket1.Socket.ActiveConnections-1 do begin
		s:=serversocket1.Socket.Connections[ii].ReceiveText;

		if s <> '' then

			List := TStringList.Create;
			try
				zmienna3 := PChar(s);
				ExtractStrings(['~'], [],zmienna3  , List);
			



for iii:=listbox1.items.count-1 downto 0 do
                         begin


if (list[0]=listbox1.items[iii])and (list[1]=listbox2.items[iii])



    then
    begin

    	 		Memo1.Lines.Add('Użytkownik: '+list[0] + ' IP: ' + Socket.RemoteAddress+'   wysyla wiadomosc:   '+list[2]);
 				for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do

 					serversocket1.Socket.Connections[i].SendText('odbierz~'+list[1]+' > ' +list[2]);

            end;
                       end;

   
			finally
				List.Free;
			end;
		end;
	end;

działanie kodu (on Client write):
Z początku program odbiera dane od podłączonych klientów..

Dzieli odebrany ciąg znaków, według znaku "~" którym oddzielane są komendy.

Sprawdza czy wyslany login i hasło zgadzają sie z tymi zapisanymi w listbox1 oraz listbox2

Dopisuje do memo1 informacje o operacji

otwiera pętlę wysyłania wiadomości do czekających klientów...

Na moje oko, jest wszystko poprawnie, nie wiem czemu nie działa :(

Jeżeli potrzebne będzie więcej informacji to proszę pytać...

Proszę o pomoc

0
  1. idź pan w buroki z takim formatowaniem
  2. if (list[0]=listbox1.items[iii])and (list[1]=listbox2.items[iii]) wypadało by sprawdzić czy w ogóle list[1] istnieje (teoretycznie list[0] jest)
  3. odpal serwer z delphi i zobacz gdzie się zatrzyma, ew postaw breakpointa i zobacz na czym się wywali
0
  1. krytyka, krytyka :( brak konstruktywnego myślenia
  2. list[1] na 100 % jest...

Postawiłem break pointa.

Wywaliło tutaj:

user image

0
seba22 napisał(a)
  1. krytyka, krytyka :( brak konstruktywnego myślenia

poświęcił byś 30 sekund na przeformatowanie tego cuda i nie było by krytyki

  1. list[1] na 100 % jest...

Postawiłem break pointa.
Wywaliło tutaj:

a ja Ci mówię, że na 100% nie ma

0

Witaj,

  1. Gdybyś dał sugestie, to z przyjemnością i wdzięcznością bym się tym zajął, nie jestem w tym oblatany, ale staram się jak mogę.

Słuchaj, postawiłem showmessage(s); na samym początku zaraz po:
s:=serversocket1.Socket.Connections[ii].ReceiveText;

I okazało się że:

jeżeli jest jeden klient s: zawsze przyjmuje dobre wartości.
jeżeli są 2 klienty s:
w pierwszej turze, przyjmuje dobre wartości xxx~xxx~xxx
w drugiej turze jest puste, i program wysypuje :(

Jak się przed tym zabezpieczyć, i czemu jest puste ? !

0
  1. masz cały art o formatowaniu. Głównie chodzi mi o to rozstrzelenie textu, które bardo utrudnia połapanie się

co do pytania to

  1. nie używam TServerSocket (wolę robić po swojemu na wątkach)
  2. to
for ii:=0 to ServerSocket1.Socket.ActiveConnections-1 do begin
  s:=serversocket1.Socket.Connections[ii].ReceiveText;

jest dla mnie dziwne bo lecisz po WSZYSTKICH połączeniach niezależnie od tego, który klient coś wysłał. W efekcie przy dwóch klientach podłączonych jeśli wyśle coś pierwszy to w pierwszym przebiegu odbierzesz to co wysłał a w drugim nie odbierzesz nic bo drugi nic nie wysłał.
Jak nic nie wysłął to

if s <> '' then
// <- tu by się begin przydał i powinno działać
  List := TStringList.Create; //to się nie wykona
try //ale od tego miejsca już tak niezależnie czy s <> '' czy nie

BTW w jakim zdarzeniu wywołujesz powyższy kod?

ale i tak całe to wywołanie jest dla mnie dziwne - jak będziesz miał 100 klientów podpiętych i jeden coś wyśle to serwer po prostu Ci umrze na jakieś 10 minut bo pozostałe 99 klientów da Ci s = '' ale dopiero po 6 sekundach każdy (taki jest zazwyczaj ReadTimeOut ustawiony

0
  1. Przepraszam, myślałem że chodzi Ci o składnie

  2. To jest zdarzenie On Client Read

Założenie jest takie...
Klient powiedzmy umownie 1 wysyła tekst do serwera.

Serwer odbiera ten tekst, i wysyła do wszystkich klientów łącznie ! z tym co wysłał !

I w takiej konwencji chciał bym to utrzymać.

Jeżeli tam gdzie zasugerowałeś wstawiłem begin, to niestety działa tylko jeden klient, drugiego już w ogóle nie bierze.

// Edytowane:

Dziękuję, wstawiłem cały kod odpowiedzialny za wysyłanie danych itp, po :
List := TStringList.Create; //to się nie wykona

:)
Bo jeżeli jest puste, to ma się nie wykonać cała operacja, a nie tylko tworzenie list-a.

0

to przecież OnClientRead przekazuje Ci socket, z którego nadeszło połączenie (Socket: TCustomWinSocket) więc po co sprawdzasz wszystkie??

powinno robić to samo co powyższe

var
  List: TStringList;
  i: integer;
  s: string;
begin
  s := Socket.ReceiveText;
  if s <> '' then
  begin
    List := TStringList.Create;
    try
      ExtractStrings(['~'], [], PChar(s), List);
      Memo1.Lines.Add('Użytkownik: ' + list[0] + ' IP: ' + Socket.RemoteAddress + ' wysyla wiadomosc:   ' + list[2]);
      for i := 0 to ServerSocket1.Socket.ActiveConnections - 1 do
        serversocket1.Socket.Connections[i].SendText('odbierz~' + list[1] + ' > ' + list[2]);
    finally
      FreeAndNil(List);
    end;
  end;
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1