Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

проблемы с Winsock [D7, WinXP]


Foccer ©   (2009-04-25 11:54:00) 

Здравствуйте уважаемые.
Я студент. Нам дали задание сделать пару проектов с помощью этой либы(если не ошибаюсь)
одна из задач передача файла посредством протокола UDP

в этой процедуре идет коннект к серверу
procedure TForm1.ConnectBtnClick(Sender: TObject);
begin
// connect to the server
sClient:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
with ServerAddr do begin
    sin_family:=AF_INET;
    sin_addr.S_addr:=inet_addr(Pchar(AddrEdit.Text));
    sin_port:=htons(45);
end;
if connect(sClient,ServerAddr,sizeof(ServerAddr)) = SOCKET_ERROR
   then begin
    LogEdit.Lines.Add('Connection failed');
    LogEdit.Lines.Add(inttostr(WSAGetLastError));
    status:=false;
   end
   else begin
    LogEdit.Lines.Add('Server connected');
    status:=true;
   end;
end;

а вот в этой процедуре идет отправка файла
procedure TForm1.SendFileBtnClick(Sender: TObject);
var
 sFile:TFileStream;
begin
// Send file to the server
sFile.Create(FileEdit.Text,fmOpenRead);
sFile.Position:=0;
if status = true
  then begin
   LogEdit.Lines.add(BoolToStr(Status));
   ret:=send(sClient,sFile,sizeof(sFile),0);
   if (ret = SOCKET_ERROR)
     then begin
        LogEdit.Lines.Add('Send failed');
        LogEdit.Lines.Add(IntToStr(WSAGetLastError));
     end
     else begin
        LogEdit.Lines.Add('File send complete');
     end;
   end
  else begin
   LogEdit.Lines.Add('The server not connected');
   LogEdit.Lines.Add(inttostr(WSAGetLastError));
  end;
end;

Собственно сам модуль запуска сервера с помощью баттона
procedure TForm1.StartServerBtnClick(Sender: TObject);
begin
// Start server on this PC (local)
WSAStartup(MakeWord(2,0),WSADATA);
sServer:=Socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
with LocalAddr do begin
     sin_family:=AF_INET;
     sin_addr.S_addr:=inet_addr(PChar(LocalAddrEdit.Text));
     sin_port:=htons(45);
end;
bind(sServer,LocalAddr,sizeof(LocalAddr));
listen(sServer,4);
iSize:=sizeof(LocalAddr);
sClient:=accept(sServer,@LocalAddr,@iSize);
closesocket(sServer);
end;

вроде все правильно
запускаю клиент пишет есть подключение к серверу
но когда нажимаю на отправку файла просто вылетает
ошибка access violation. дальше нуль эмоций.
Прошу подсказать что я пропустил.


Сергей М.   (2009-04-28 19:58:00) [1]

Лыбу строй преподу)


foccer   (2009-04-28 19:41:00) [2]

^_^


Сергей М.   (2009-04-28 19:23:00) [3]

Отладчик в зубы  - и вперед !


> не догоняю


За "догон" платить следует.

Готов ?

$500 - и получишь готовое.


foccer   (2009-04-28 18:27:00) [4]

сервер без неблок режим и селекта
str:=tmemorystream.create;

   RecvBytes:=recv(sServer,str.memory^,str.Size,0);
   if recvbytes < 0 then begin
      LogMemo.Lines.Add('recv error');
      break;
      closesocket(sServer);
   end;
   str.SaveToFile('c:\delphi\1.dat');

клиент
total:=0;
while total <= sFile.Size do begin
    SentBytes:=sendto(sClient,sFile.memory^,sFile.Size,0,ServerAddr,sizeof(ServerAdd r));
    if (SentBytes = SOCKET_ERROR)
        then begin
             LogEdit.Lines.Add('Send failed');
             LogEdit.Lines.Add(IntToStr(WSAGetLastError));
             CloseSocket(sClient);
             Break;
        end;
    LogEdit.Lines.Add('File send started');
    LogEdit.Lines.Add(inttostr(SentBytes));
    total:= total + SentBytes;
end; //end while

на стороне клиента выдает
socket failed с номером 6
так и не догоняю где ошибка
прошу помочь


Сергей М.   (2009-04-27 08:23:00) [5]


> клиент корректен или нет?


При использовании UDP за вызовом connect() обычно следуют send()/recv(), иначе connect() лишен смысла.
sendto()/recvfrom() же обычно используются если перед ними не было вызова connect()


> UDP через sendto посылает одну датаграмму


Да.


> пошлет файл целиком одним разом или нет


Смотря какого размера файл.
Кр.того, UDP не гарантирует доставку, так что отправленная дейтаграмма может и не дойти до адресата.


> то что сервер принимает данные или нет я могу узнать через
> Select?


Можешь, на то и select().


> как можно избежать зависания серверной части?


Либо задействовать неблок.режим либо вынести трасп.логику в доп.тред.


foccer   (2009-04-26 21:59:00) [6]

после прочтения еще нескольких примеров и документаций получилось вот что
клиент:
procedure TForm1.ConnectBtnClick(Sender: TObject);
begin
// connect to the server
sClient:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
with ServerAddr do begin
    sin_family:=AF_INET;
    sin_addr.S_addr:=inet_addr(Pchar(AddrEdit.Text));
    sin_port:=htons(775);
end;
with LocalAddr do begin
    sin_family:=AF_INET;
    sin_addr.S_addr:=inet_addr(Pchar(LocalAddrEdit.Text));
    sin_port:=htons(775);
end;
if connect(sClient,ServerAddr,sizeof(ServerAddr)) = 0
   then begin
    LogEdit.Lines.Add('Server connected');
    status:=true;
   end
   else begin
    LogEdit.Lines.Add('Connection failed');
    LogEdit.Lines.Add(inttostr(WSAGetLastError));
    CloseSocket(sClient);
    status:=false;
   end;
end;
в данном случае с помощью UDP можно коннектиться,т.е. имитирует.

procedure TForm1.SendFileBtnClick(Sender: TObject);
begin
// Send file to the server
if status = true
  then begin
SentBytes:=sendto(sClient,sFile.memory^,sFile.Size,0,ServerAddr,sizeof(ServerAdd r));
   if (SentBytes = SOCKET_ERROR)
     then begin
        LogEdit.Lines.Add('Send failed');
        LogEdit.Lines.Add(IntToStr(WSAGetLastError));
        CloseSocket(sClient);
     end
     else begin
        LogEdit.Lines.Add('File send started');
        LogEdit.Lines.Add(inttostr(SentBytes));
     end
  end  
  else begin
   LogEdit.Lines.Add('The server not connected');
   LogEdit.Lines.Add(inttostr(WSAGetLastError));
   CloseSocket(sClient);
  end;
end;
хотелось б узнать клиент корректен или нет? прочитал что UDP через sendto посылает одну датаграмму, т.е. он пошлет файл целиком одним разом или нет?
если то получается sendto мне надо закинуть в цикл?
а то что сервер принимает данные или нет я могу узнать через Select?
и как можно избежать зависания серверной части?


Сергей М.   (2009-04-26 21:18:00) [7]


> прочитал
> что listen используется для Sock_Stream


Именно.
И accept() тоже.

Вместо этих вызовов нужен recv или recvfrom


FireMan_Alexey   (2009-04-25 23:37:00) [8]

http://Book.itep.ruГлава 7.1 по моему)


Foccer   (2009-04-25 20:52:00) [9]

и вот что еще прочитал
что listen используется для Sock_Stream
не отрицаю кое что содрал кое что сам....
тогда как быть все таки?


Foccer   (2009-04-25 20:45:00) [10]

и как мне быть вообще?


Сергей М.   (2009-04-25 19:47:00) [11]


> как можно проверить соединен ли клиент на стороне сервера?


Никак.
UDP вообщене подразумевает соединение.

Код, который ты откуда-то содрал и попытался приспособить к решению своего задания, имеет отношение к TCP, а не к UDP.


Foccer   (2009-04-25 16:41:00) [12]

подскажите пожалуйста
как можно проверить соединен ли клиент на стороне сервера?


Foccer   (2009-04-25 12:24:00) [13]

ошибся надо еще писать процедуру сохранения(приема) данных
а вот на счет потоков вопрос остался.


Foccer   (2009-04-25 12:21:00) [14]

спасибо сработало правда я не понял куда он его сохраняет.
у меня есть еще один вопрос
нужно ли мне использовать потоки?


easy   (2009-04-25 12:13:00) [15]

sFile:=TFileStream.Create


Foccer   (2009-04-25 12:12:00) [16]

в FileEdit.text передается путь к файлу


Foccer   (2009-04-25 12:11:00) [17]


> easy ©   (25.04.09 12:07) [1]
>
> sFile.Create(FileEdit.Text,fmOpenRead);

а что в нем не так?


easy   (2009-04-25 12:07:00) [18]

sFile.Create(FileEdit.Text,fmOpenRead);


Наверх

Титульная страница Поиск, карта сайта Написать письмо