Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
Вниз
Сервер TCP, потоки Найти похожие ветки
← →
Nucer (2007-11-06 20:47) [0]Есть поток ServerThread, есть форма. Поток шлет форме сообщения (SendMessage) Connect, Disconnect и Packet. Сообщение Connect шлется только тогда, когда сокет готов к записи, чтобы в обработчике формы этого сообщения можно было сразу вызывать функцию send. Чтобы закрыть соединение, достаточно установить переменной kill значение true. Правильно ли все это реализовано?
[code]
var
ss:array [0..9] of record
sock:TSocket;
d:TServer;
active:boolean;
kill:boolean;
time:TDateTime;
ready:boolean;
end;[/code]
[code]procedure ServerThread;
var
Addr:TSockAddr;
Data:TWSAData;
Len,I,Size:Integer;
FDSetR,FDSetW:TFDSet;
ok:boolean;
SelectTimeOut:TTimeVal;
tmp:string;
buf:array [0..$FFFF] of byte;
procedure Kick(i:integer);
begin
CloseSocket(ss[I].sock);
if ss[i].active then SendMessage(frmMain.Handle,WM_SERVER_MSG,M_Disconnect,i);
ss[i].active:=false;
end;
begin
try
WSAStartup($101,Data);
for i:=0 to length(ss)-1 do
begin
ss[i].active:=false;
ss[i].kill:=false;
ss[i].ready:=false;
ss[i].d.index:=-1;
end;
ss[0].sock:=Socket(AF_Inet,Sock_Stream,0);
ss[0].active:=true;
SelectTimeOut.tv_sec:=1;
SelectTimeOut.tv_usec:=0;
Addr.sin_family:=AF_Inet;
Addr.sin_port:=HToNS(g.ServerPort);
Addr.sin_addr.S_addr:=InAddr_Any;
FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
if Bind(ss[0].sock,Addr,SizeOf(TSockAddr))=SOCKET_ERROR then
begin
SendMessage(frmMain.Handle,WM_SERVER_MSG,M_SOCKETERROR,WSAGetLastError);
exit;
end;
Listen(ss[0].sock,SoMaxConn);
SendMessage(frmMain.Handle,WM_SERVER_MSG,M_SERVERLISTEN,0);
while True do
begin
//Закрываем указанные соединения
for i:=1 to High(ss) do if ss[i].active then if ss[i].kill then kick(i);
FD_Zero(FDSetR);
FD_Zero(FDSetW);
for i:=0 to High(ss) do if ss[i].active then
begin
FD_Set(ss[I].sock,FDSetR);
if not ss[I].ready then FD_Set(ss[I].sock,FDSetW);
end;
Select(0,@FDSetR,@FDSetW,nil,@SelectTimeOut);
for i:=1 to High(ss) do if ss[i].active then
begin
if FD_IsSet(ss[i].sock,FDSetR) then
begin
size:=recv(ss[i].sock,buf[0],Length(buf),0);
if size<=0 then kick(i) else with ss[i].d do
begin
SetLength(tmp,size);
move(buf[0],tmp[1],size);
recv.buf:=recv.buf+tmp;
while length(recv.buf)>2 do
begin
size:=ord(recv.buf[1])+ord(recv.buf[2])*256;
if length(recv.buf)<size then break;
recv.pck:=copy(recv.buf,1,size);
delete(recv.buf,1,size);
SendMessage(frmMain.Handle,WM_SERVER_MSG,M_Packet,i);
end;
end;
end;
end;
for i:=1 to High(ss) do if ss[i].active then if not ss[i].ready then
begin
if FD_IsSet(ss[i].sock,FDSetW) then
begin
ss[i].ready:=true;
SendMessage(frmMain.Handle,WM_SERVER_MSG,M_CONNECT,i);
end;
end;
if FD_IsSet(ss[0].sock,FDSetR) then for i:=1 to High(ss) do if not ss[i].active then
begin
Len:=SizeOf(TSockAddr);
ss[i].sock:=Accept(ss[0].sock,@Addr,@Len);
ss[i].d.ip:=inet_ntoa(Addr.sin_addr);
ok:=true;
if ok then
begin
ss[i].kill:=false;
ss[i].d.recv.buf:="";
ss[i].d.recv.pck:="";
ss[i].d.index:=-1;
ss[i].active:=true;
ss[i].ready:=false;
end;
break;
end;
end;
except
Messagebox(0,PChar("ServerThread","Error",MB_ICONERROR);
end;
end;[/code]
← →
Сергей М. © (2007-11-07 09:00) [1]Жуткая каша)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.02;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.051 c