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

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

Помогите с winsocket в WinAPI [D6, D7, WinXP]


Страницы:   1 2

chemelin ©   (2008-01-15 12:30:00) 

Нужно написать на winsocket без VCL компонентов клиент-сервер которые будут обмениваться данными, помогите пожалуйста, если можно исходник или ссылки на статьи или готовые варианты реализации, буду очень благодарен, малое представление имею о winsocket но не могу реализовать передачу данных!


Сергей М.   (2008-01-15 14:05:00) [21]


> Вот смотри


Ну вижу.

И что ?


chemelin   (2008-01-15 13:54:00) [22]


> Не надо.

Я видел что я неправильно был здесь написал

recv(sServerListen, buf, 1024, 0);
edit1.Text  := sRecvStr;

не хотел снова лепить сообщение.
Вот смотри:

...
var
sRecvBuff, sSendBuff : array [0..255] of char;
ret:Integer;
s:String;
begin
while(true) do
 begin
  ret := recv(sock, sRecvBuff, 1024, 0);
  if (ret = 0) then
   Continue
  else
   if (ret = SOCKET_ERROR) then
    begin
     MessageBox(0, 'Ошибка получения данных', 'Внимание!!!', 0);
     exit;
    end;

  s:=sRecvBuff;
  if s[Length(s)]=#10 then
   s:=Copy(s, 1, Length(s)-2);
  if s<>'get' then
   continue;
  sSendBuff:='Command get OK';

  ret := send(sock, sSendBuff, sizeof(sSendBuff), 0);
  if (ret = SOCKET_ERROR) then
    begin
     MessageBox(0, 'Ошибка передачи данных', 'Внимание!!!', 0);
     break;
    end;
 end;
CloseSocket(sock);
...


Сергей М.   (2008-01-15 13:49:00) [23]


> выложу здесь кодинг


Не надо.

Твоему дурному примеру могут последовать неокрепшие умы твентинпрограммеров)


chemelin   (2008-01-15 13:47:00) [24]

О, по идее разобрался. Когда сделаю что будет все работать как надо, выложу здесь кодинг, для примера другим!


Сергей М.   (2008-01-15 13:47:00) [25]


> для чего она?


Для ожидания запросов на соединение и собственно установки соединения.


> Делаю фот так


Полную ерунду ты делаешь.

Справку по Winsock API ты вообще читал перед тем как лепить код ?

Там же черным по белому написано:

The Windows Sockets recv function receives data from a socket.

int recv (

   SOCKET s,
   char FAR* buf,
   int len,
   int flags
  );

..

s

[in] A descriptor identifying a connectedsocket.

А ты что толкаешь первым параметром ? Ты туда толкаешь дескриптор слушающегосокета.
Разницу между слушающим сокетом и сокетом, ассоциированным с успешно установленным соединением, осюсяешь ?
Получается что не осюсяешь.
Ну так вперед - читать документацию !


chemelin   (2008-01-15 13:28:00) [26]


> Функция accept()

а для чего она?
Делаю фот так:

...
recv(sServerListen, buf, 1024, 0);
edit1.Text  := sRecvStr;
...

в чем ошибка?


Сергей М.   (2008-01-15 13:17:00) [27]

Функция accept() не предназначена для приема данных, для этого существует ф-ция recv()


chemelin   (2008-01-15 13:09:00) [28]


> пользуйтесь кнопкой "код" справа от поля ввода

Давно был на этом форуме, забыл за кнопку "код", извиняюсь.

Делал вот так:

...
var
sRecvStr : array [0..255] of char;
...

  //Приём нового соединения
 sClient :=accept(sServerListen, @sRecvStr, @iSize);
  if sClient = INVALID_SOCKET then
   begin
    TestWinSockError('accept');
   end;
    edit1.Text  := sRecvStr;
...

После приёма данных, в edit1 выводит такой вот символ "|" заместь "get"


Сергей М.   (2008-01-15 13:05:00) [29]


> chemelin   (15.01.08 12:51) [3]


Что говорит отладчик ?


Григорьев Антон   (2008-01-15 12:58:00) [30]

Навскидку ошибок не видно, но код нити TCPClientThread не приведён, может, там что не так. Только просьба - пользуйтесь кнопкой "код" справа от поля ввода, а то неоформленный листинг читать тяжело.


chemelin   (2008-01-15 12:54:00) [31]

Вот кусочек кода с UDP протокола, работает. Но не могу перенести этот код в TCP протокол (в тот код что писал выше)!

//Прослушивание
iSize:=sizeof(clientaddr);
if recvfrom(sServerListen, sRecvStr, 255, 0,
    clientaddr, iSize)<>SOCKET_ERROR then
 Label1.Caption:=sRecvStr;


chemelin   (2008-01-15 12:51:00) [32]


> Что конкретно "не выходит" ?

Не выходит корректно передать драные с клиента на сервер и на оборот, допустим с клиента передаю строку "Hello"  и чтобы на сервера она отобразилась в Edit'e, ну и обратная связь! (образный пример)


Сергей М.   (2008-01-15 12:44:00) [33]


> не выходит


Что конкретно "не выходит" ?


chemelin   (2008-01-15 12:38:00) [34]

продолжение вопроса...
Вот у меня есть акая реализация сервер-клмент, подправьте что не так.
TCPClient
procedure TestWinSockError(S:String);
var
iErr:Integer;
sFullErr:String;
begin
sFullErr:='Неизвестная ошибка';
iErr:=WSAGetLastError();

case iErr of
 WSANOTINITIALISED: sFullErr:='Нужно сначала вызвать функцию WSASturtup, а потом создавать сокет';
WSAENETDOWN: sFullErr:='Cвязь нарушена, возможные причины - отошёл кабель или отключились от Интернета';
WSAEADDRINUSE: sFullErr:='Указанный адрес уже используется';
WSAEFAULT: sFullErr:='Параметры name и namelen не соответствуют выбранной адресации. Параметр namelen может быть меньше необходимого значения, а name содержать некорректные данные';
WSAEINPROGRESS: sFullErr:='Выполняется операция в блокирующем режиме. Вы уже запустили на выполнение какую-то функцию и нужно дождаться завершения её работы';
WSAEINVAL: sFullErr:='Сокет уже связан с адресом';
WSAENOBUFS: sFullErr:='Недостаточно буферов, слишком много соединений';
WSAENOTSOCK: sFullErr:='Неверный дескриптор сокета';
 WSAEISCONN: sFullErr:='Сокет уже подключён';
 WSAEMFILE: sFullErr:='Нет больше доступных дескрипторов';
end;

MessageBox(0, PChar('Ошибка в функции '+S+' - '+sFullErr), 'Ошибка', 0);
end;

function LookupName(name:String): TInAddr;
var
HostEnt: PHostEnt;
InAddr: TInAddr;
begin
if name[4]='.' then
 InAddr.s_addr := inet_addr(PChar(name))
else
 begin
 HostEnt := gethostbyname(PChar(name));
 FillChar(InAddr, SizeOf(InAddr), 0);
 if HostEnt <> nil then
  begin
   with InAddr, HostEnt^ do
    begin
     S_un_b.s_b1 := h_addr^[0];
     S_un_b.s_b2 := h_addr^[1];
     S_un_b.s_b3 := h_addr^[2];
     S_un_b.s_b4 := h_addr^[3];
    end;
  end
 end;
 Result := InAddr;
end;

procedure TTCPClientForm.btSendClick(Sender: TObject);
var
wData : WSADATA;
sServerListen: TSOCKET;
server_addr : sockaddr_in;
iRet : Integer;
sRecvBuff : array [0..255] of char;
begin
// Загрузка WinSock
if WSAStartup(MAKEWORD(1,1), wData) <> 0 then
begin
  MessageBox(0, 'Не могу загрузить WinSock', 'Ошибка', 0);
  exit;
end;

// Создание сокета
sServerListen := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if sServerListen = INVALID_SOCKET then
 begin
  MessageBox(0, 'Ошибка создания сокета', 'Ошибка', 0);
  exit;
 end;

// Запонение структуры адреса
server_addr.sin_addr.s_addr := htonl(INADDR_ANY);
server_addr.sin_family := AF_INET;
server_addr.sin_port := htons(5050);
server_addr.sin_addr := LookupName(edServer.Text);

if (connect(sServerListen, server_addr, sizeof(server_addr)) = SOCKET_ERROR) then
 begin
  TestWinSockError('Send');
  exit;
 end;

sRecvBuff:='get';
iRet := send(sServerListen, sRecvBuff, 3, 0);
if (iRet = SOCKET_ERROR) then
  begin
   MessageBox(0, 'Ошибка передачи данных', 'Внимание!!!', 0);
   exit;
  end;

iRet := recv(sServerListen, sRecvBuff, 1024, 0);
if (iRet = SOCKET_ERROR) then
 begin
  MessageBox(0, 'Ошибка получения данных', 'Внимание!!!', 0);
  exit;
 end;  

edServer.Text:=sRecvBuff;
CloseSocket(sServerListen);
end;

end.
---------------------------------
TCPServer
procedure TestWinSockError(S:String);
var
iErr:Integer;
sFullErr:String;
begin
sFullErr:='Неизвестная ошибка';
iErr:=WSAGetLastError();

case iErr of
 WSANOTINITIALISED: sFullErr:='Нужно сначала вызвать функцию WSASturtup, а потом создавать сокет';
WSAENETDOWN: sFullErr:='Cвязь нарушена, возможные причины - отошёл кабель или отключились от Интернета';
WSAEADDRINUSE: sFullErr:='Указанный адрес уже используется';
WSAEFAULT: sFullErr:='Параметры name и namelen не соответствуют выбранной адресации. Параметр namelen может быть меньше необходимого значения, а name содержать некорректные данные';
WSAEINPROGRESS: sFullErr:='Выполняется операция в блокирующем режиме. Вы уже запустили на выполнение какую-то функцию и нужно дождаться завершения её работы';
WSAEINVAL: sFullErr:='Сокет уже связан с адресом';
WSAENOBUFS: sFullErr:='Недостаточно буферов, слишком много соединений';
WSAENOTSOCK: sFullErr:='Неверный дескриптор сокета';
 WSAEISCONN: sFullErr:='Сокет уже подключён';
 WSAEMFILE: sFullErr:='Нет больше доступных дескрипторов';
end;

MessageBox(0, PChar('Ошибка в функции '+S+' - '+sFullErr), 'Ошибка', 0);
end;

function TestFuncError(iErr:Integer; FuncName:String):Boolean;
begin
Result:=false;
if iErr = SOCKET_ERROR then
 begin
  TestWinSockError(FuncName);
  Result:=true;
 end;
end;

procedure TForm1.bStartServerClick(Sender: TObject);
var
wData : WSADATA;
sServerListen, sClient : TSOCKET;
localaddr, clientaddr : sockaddr_in;
iSize : Integer;
s1 : TCPClientThread;
begin
// Загрузка WinSock
if WSAStartup(MAKEWORD(1,1), wData) <> 0 then
begin
  MessageBox(0, 'Не могу загрузить WinSock', 'Ошибка', 0);
  exit;
end;

// Создание сокета
sServerListen := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if sServerListen = INVALID_SOCKET then
 begin
  MessageBox(0, 'Ошибка создания сокета', 'Ошибка', 0);
  exit;
 end;

// Запонение структуры адреса
localaddr.sin_addr.s_addr := htonl(INADDR_ANY);
localaddr.sin_family := AF_INET;
localaddr.sin_port := htons(5050);

//Связывание сокета с локальным адресом
if bind(sServerListen, localaddr, sizeof(localaddr)) = SOCKET_ERROR then
 begin
  TestWinSockError('Bind');
  exit;
 end;

//Прослушивание
if TestFuncError(listen(sServerListen, 4), 'Listen') then
 exit;

MessageBox(0, 'Сервер запущен', 'Внимание!!!', 0);
while (true) do
 begin
  iSize := sizeof(clientaddr);

  //Приём нового соединения
  sClient := accept(sServerListen, @clientaddr, @iSize);
  if sClient = INVALID_SOCKET then
   begin
    TestWinSockError('accept');
    break;
   end;

  // Соединение принято, создаём поток
  s1:=TCPClientThread.Create(true);
  s1.Sock:=sClient;
  s1.Resume;
 end;
closesocket(sServerListen);
end;

end.

Пробывал сам сделать не выходит!


Страницы:   1 2

Наверх

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