Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |

29.10.2009, 02:39
|
|
Участник форума
Регистрация: 22.11.2008
Сообщений: 142
Провел на форуме: 636446
Репутация:
32
|
|
Особенности WinSock2
Вопрос первый:
Как правильней отправлять текст?
Вариант первый (Код на Delphi):
Код:
function SendText(Sock: TSocket; S: String): Integer;
begin
Result:=Send(Sock, PChar(S)^, Length(S), 0);
end;
Вариант второй (Код на Delphi):
Код:
function SendText(Sock: TSocket; S: String): Integer;
var
MainBuff: Array[0..1023] of Char;
iSize: Integer;
begin
Result:=0;
While (Length(S)>0) do
begin
iSize:=Length(S);
if (iSize>SizeOf(MainBuff)) then iSize:=SizeOf(MainBuff);
FillChar(MainBuff, SizeOf(MainBuff), 0);
CopyMemory(@MainBuff, PChar(S), iSize);
Delete(S, 1, iSize);
Result:=Result+Send(Sock, MainBuff, iSize, 0);
end;
end;
Вопрос второй:
Правильно ли я перевожу в неблокирующий режим?
Фрагмент кока (код на Delphi):
Код:
var
Sock: TSocket;
iMode: Cardinal;
....
begin
....
Sock:=Socket(AF_INET, SOCK_STREAM, 0);
if (Sock=INVALID_SOCKET) then Raise Exception.Create('Ошибка создания сокета');
if (Connect(Sock, @SockAddr, Sizeof(SockAddr))=0) then
begin
if NoneBlock then
begin
iMode:=1;
IOCtlSocket(Sock, FIONBIO, iMode);
end;
...
|
|
|

29.10.2009, 10:49
|
|
Reservists Of Antichat - Level 6
Регистрация: 05.03.2007
Сообщений: 1,985
Провел на форуме: 3288241
Репутация:
3349
|
|
Вопрос 1:
Вариант Result:=Send(Sock, PChar(S)^, Length(S), 0); приемлем для строк относительно не большого размера. Чтобы люде не говорили, что данные не смогт сразу послаться итд итп. но это уже более низкий уровень будет думать. А от тебя данные уйдут в ядро и вернется значение сколько данных послан. Именно послано, а не дошло.
Второй вариант - принципиально не правильный. Зачем копировать данные во временный буфер? Юзай указатели. т.е. это можно оформить примерно так:
Код:
function SendText(Sock: TSocket; S: String): Integer;
var
SendLen: Integer;
BufStart : pchar;
BufLen : integer;
begin
BufLen := Length(s); // сразу вычислим размер, чтобы потом постоянно не считать
BufStart := @s[1]; // установим указатель на начало строки
While ( BufLen > 0) do // если есть что отправлять
begin
if BufLen < 1024 then SendLen := BufLen else BufLen := 1024; // вычислим сколько байт отправлять. Но не более 1024 (1024- это так к примеру)
SendLen := Send(Sock, BufStart, SendLen, 0); // отправим
if SendLen <= 0 then break; // если ошибка была то выйти из цикла отправки
BufStart := pchar(dword(BufStart) + SendLen); // переместим указатель дальше
BufLen := BufLen - SendLen; // уменьшим кол-во оставшихся данных
end;
end;
т.е. примерно так должно идти.
Второй вопрос. В принципе правильно.
|
|
|

29.10.2009, 15:46
|
|
Постоянный
Регистрация: 13.12.2008
Сообщений: 354
Провел на форуме: 1747641
Репутация:
175
|
|
Сообщение от slesh
Код:
function SendText(Sock: TSocket; S: String): Integer;
var
SendLen: Integer;
BufStart : pchar;
BufLen : integer;
begin
BufLen := Length(s); // сразу вычислим размер, чтобы потом постоянно не считать
BufStart := @s[1]; // установим указатель на начало строки
While ( BufLen > 0) do // если есть что отправлять
begin
if BufLen < 1024 then SendLen := BufLen else BufLen := 1024; // вычислим сколько байт отправлять. Но не более 1024 (1024- это так к примеру)
SendLen := Send(Sock, BufStart, SendLen, 0); // отправим
if SendLen <= 0 then break; // если ошибка была то выйти из цикла отправки
BufStart := pchar(dword(BufStart) + SendLen); // переместим указатель дальше
BufLen := BufLen - SendLen; // уменьшим кол-во оставшихся данных
end;
end;
Отлично, спасибо за код! Я не знал о таком способе, не очень люблю работать с указателями.
|
|
|

29.10.2009, 23:29
|
|
Участник форума
Регистрация: 22.11.2008
Сообщений: 142
Провел на форуме: 636446
Репутация:
32
|
|
Сообщение от slesh
Вопрос 1:
Второй вариант - принципиально не правильный. Зачем копировать данные во временный буфер? Юзай указатели. т.е. это можно оформить примерно так:
Код:
function SendText(Sock: TSocket; S: String): Integer;
var
SendLen: Integer;
BufStart : pchar;
BufLen : integer;
begin
BufLen := Length(s); // сразу вычислим размер, чтобы потом постоянно не считать
BufStart := @s[1]; // установим указатель на начало строки
While ( BufLen > 0) do // если есть что отправлять
begin
if BufLen < 1024 then SendLen := BufLen else BufLen := 1024; // вычислим сколько байт отправлять. Но не более 1024 (1024- это так к примеру)
SendLen := Send(Sock, BufStart, SendLen, 0); // отправим
if SendLen <= 0 then break; // если ошибка была то выйти из цикла отправки
BufStart := pchar(dword(BufStart) + SendLen); // переместим указатель дальше
BufLen := BufLen - SendLen; // уменьшим кол-во оставшихся данных
end;
end;
т.е. примерно так должно идти.
Второй вопрос. В принципе правильно.
Принципиально неправильный - из-за нерациональности с памятью?
Проверил твою идею.
Да указатели действительно облегчили жизнь.
ЗЫ походу не BufLen а SendLen и ещё походу BufStart ты тут в конце указатель забыл 
Последний раз редактировалось Flenov; 30.10.2009 в 03:09..
|
|
|

30.10.2009, 03:08
|
|
Участник форума
Регистрация: 22.11.2008
Сообщений: 142
Провел на форуме: 636446
Репутация:
32
|
|
А приёмку я осуществляю верно?
Код:
function ReceiveText(Sock: TSocket; var S: String): Integer;
var
MainBuff: Array[0..1023] of Char;
iSize: Integer;
begin
Result:=0;
While True do
begin
FillChar(MainBuff, SizeOf(MainBuff), 0);
iSize:=Recv(Sock, MainBuff, SizeOf(MainBuff), 0);
if (iSize<1) then Break;
S:=S+String(MainBuff);
Result:=Result+iSize;
end;
end;
|
|
|

30.10.2009, 15:01
|
|
Постоянный
Регистрация: 13.12.2008
Сообщений: 354
Провел на форуме: 1747641
Репутация:
175
|
|
Код:
function SendText(Sock: TSocket; S: String): Integer;
var
MainBuff: Array[0..1023] of Char;
iSize: Integer;
begin
Result:=0;
While (Length(S)>0) do
begin
iSize:=Length(S);
if (iSize>SizeOf(MainBuff)) then iSize:=SizeOf(MainBuff);
FillChar(MainBuff, SizeOf(MainBuff), 0);
CopyMemory(@MainBuff, PChar(S), iSize);
Delete(S, 1, iSize);
Result:=Result+Send(Sock, MainBuff, iSize, 0);
end;
end;
Код:
function ReceiveText(Sock: TSocket; var S: String): Integer;
var
MainBuff: Array[0..1023] of Char;
iSize: Integer;
begin
Result:=0;
While True do
begin
FillChar(MainBuff, SizeOf(MainBuff), 0);
iSize:=Recv(Sock, MainBuff, SizeOf(MainBuff), 0);
if (iSize<1) then Break;
S:=S+String(MainBuff);
Result:=Result+iSize;
end;
end;
Оба твои коды правильные. Они не слишком хороши в реализации. Также, долго могут выполняться следующие процедуры: FillChar(); CopyMemory();
|
|
|

30.10.2009, 22:47
|
|
Участник форума
Регистрация: 22.11.2008
Сообщений: 142
Провел на форуме: 636446
Репутация:
32
|
|
А приёмку как лучше и быстрее можно выполнить?
Кстати, я тут на днях от нехера делать DownLoader написал на чистых сокетах.
Если я статеечку напишу с исходниками - это кому-то нужно или опять всё будут говорить Flenov, ты хернёй маешься?
Последний раз редактировалось Flenov; 30.10.2009 в 23:09..
|
|
|

31.10.2009, 22:52
|
|
Постоянный
Регистрация: 13.12.2008
Сообщений: 354
Провел на форуме: 1747641
Репутация:
175
|
|
Сообщение от Flenov
А приёмку как лучше и быстрее можно выполнить?
Кстати, я тут на днях от нехера делать DownLoader написал на чистых сокетах.
Если я статеечку напишу с исходниками - это кому-то нужно или опять всё будут говорить Flenov, ты хернёй маешься?
Для новичков будет полезно, особенно если работа с Winsock.
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|