-
Иван (13.06.10 19:27) [0]Здравствуйте! Извините что отнимаю время. Хотелось бы услышать совет. У меня задача написать программу для тестирования знаний. Я выбрал модель клиент-сервер. И выбрал компоненты TcpServer и TcpClient. Пользуюсь ими впервые. Возникли сложности с принятием данных с сервера. Суть такая. На сервере имеется возможность создания тестов. При запуске клиента юзер вводит свое имя и конектится к серверу, при конекте клиент передает имя компа на сервер, затем сервер передает клиенту список имеющихся тестов либо файлы всех тестов. После чего клиент подгружает выбранный тест, проходит его и отсылает данные на сервер. Звучит просто...
Подскажите пожалуйста как это проще и лучше организовать, оптимальнее. Клиентов будет не больше 30. Вообще возникли трудности с приемом данных с сервера.
серверprocedure TForm1.TcpServer1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: string;
begin
{Здесь сервер принимает клиента}
Clients.Items.Add(clientsocket.Receiveln());
s:=TestListBox.Items.GetText;
clientsocket.Sendln(s,#$D#$A)
end;
клиентprocedure TForm1.StartClick(Sender: TObject);
var
s: string;
begin
tcpclient1.RemoteHost:=IporNameHost.Text;
tcpclient1.Open;
s:=TcpClient1.LocalHostName;
Form1.TcpClient1.Sendln(s,#$D#$A);
form2.TestsListBox.Items.Add(tcpclient1.Receiveln());
form2.ShowModal();
end;
И как вообще передать файл?
Очень благодарен за внимание. И заранее спасибо за ответы и советы! -
Иван (13.06.10 19:27)
И как вообще передать файл
ПРОТОКОЛ, ПРОТОКОЛ и еще раз ПРОТОКОЛ!
выбери из имеющихся или сам придумай протоколзапрос LOGIN, UserName<CR><LF>
ответ OK, TestFile<CR><LF>
Запрос GET, TestFile<CR><LF>
ОТВЕТ ОК, TestFileLength<CR><LF>
TestFileSource
Зачем серверу передавать имя компа? может имя пользователя? -
Здравствуйте! Переделал код. При коннекте клиент посылает имя пользователя и имя компа, далее сервер передает клиенту список имеющихся тестов, ( до сюда все работает) потом пользователь выбирает тест и клиент должен передать имя теста на сервер, сервер загружает тест и передает его клиенту. Вот не получается передать имя теста серверу...
Код:
Сервер
//мой поток
TClientDataThread = class(TThread)
private
public
ListBuffer :TStringList;
TargetList :TStrings;
procedure synchAddDataToControl;
constructor Create(CreateSuspended: Boolean);
procedure Execute; override;
procedure Terminate;
end;
//------------- TClientDataThread impl -----------------------------------------
constructor TClientDataThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FreeOnTerminate := true;
ListBuffer := TStringList.Create;
end;
procedure TClientDataThread.Terminate;
begin
ListBuffer.Free;
inherited;
end;
procedure TClientDataThread.Execute;
begin
Synchronize(synchAddDataToControl);
end;
procedure TClientDataThread.synchAddDataToControl;
begin
TargetList.AddStrings(ListBuffer);
end;
//------------- end TClientDataThread impl -------------------------------------procedure TForm1.TcpServer1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
s: string;
DataThread: TClientDataThread;
i: integer;
begin
{Здесь сервер принимает клиента}
/// create thread
DataThread:= TClientDataThread.Create(true);
// set the TagetList to the gui list that you
// with to synch with.
DataThread.TargetList := Clients.Items;
// Load the Threads ListBuffer
s := ClientSocket.Receiveln;
DataThread.ListBuffer.Add(s+' - '+ClientSocket.LookupHostName(ClientSocket.RemoteHost) +
' (' + ClientSocket.RemoteHost + ')');
// Call Resume which will execute and synch the
// ListBuffer with the TargetList
DataThread.Resume;
for I := 0 to testlistbox.Items.Count - 1 do
clientsocket.Sendln(testlistbox.items[I]);
end;
Клиентprocedure TForm1.StartClick(Sender: TObject);
var
s: string;
DataThread: TClientDataThread;
begin
tcpclient1.RemoteHost:=IporNameHost.Text;
tcpclient1.Open;
TcpClient1.Sendln(Group.Text+'/'+Name.Text);
// create thread
DataThread:= TClientDataThread.Create(true);
// set the TagetList to the gui list that you
// with to synch with.
DataThread.TargetList := form2.TestsListBox.Items;
s := tcpclient1.Receiveln;
while s <> '' do
begin
DataThread.ListBuffer.Add(s);
s := tcpclient1.Receiveln;
end;
// Call Resume which will execute and synch the
// ListBuffer with the TargetList
DataThread.Resume;
form2.ShowModal();
end;
procedure TForm2.StartTestClick(Sender: TObject);
var
s: string;
DataThread: TClientDataThread;
begin
if testslistbox.ItemIndex<>-1 then
begin
s:=testslistbox.Items[testslistbox.ItemIndex];
form1.TcpClient1.Sendln(s); //ТУТ не могу передать и получить на сервере
end
else exit;
form3.Caption:=s;
form3.ShowModal();
end;
-
1. писец... потоки тут зочем? если TcpServer в ThreadBlocking режиме -то потоки уже для тебя оформлены, если нет то нафик они нужны
про клиента молчу: отдельный поток там возможен, но не на данном этапе эволюции...
2. э 2 кнопки и 1 соединение - грабли (вторую кнопку жмем через час и вуаля - ЕРРОР)! 2 кнопки 2 соединения - твое! но придется приделать некий Session уникальный для "Логического" соединения нескольких последовательных физических подключений -
на вскидку твою задумку проще обернуть в HTTP при помощи TIdHttpServer, а клиент в виде браузера или свое приложение с TIdHttp