QUOTE
ВинСокет как-то понимает что пришел самый последний кусочек большой TCP посылки
Подтверждается каждый второй пакет, а если новые пакеты не приходят, то через 200мс. Вменяемый стек, имея данные для передачи, должен начинать эту передачу не ожидая подтверждения.
QUOTE
Реально ли это на кейловском стеке? По тестам терминалки только около мегабайта...
Реально. Замените терминалку на самонаписанное ПО.
Ну хотя-бы вот так (пример на C++ Builder):
CODE
//---------------------------------------------------------------------------
#include <vcl.h>
#include <winsock2.h>
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,0), &WSAData) != 0)
{
ShowMessage("Error: WSAStartup failed!");
}
}
//---------------------------------------------------------------------------
#define SAMPLE_RATE (130208UL)
static const unsigned char wav_hdr[]={
0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,(SAMPLE_RATE>>0)&0xFF,(SAMPLE_RATE>>8)&0xFF,(SAMPLE_RATE>>16)&0xFF,0x00,0xC0,0x27,0x09,0x00,
0x08,0x00,0x20,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00
};
HANDLE fout;
DWORD total_size;
SOCKET ADCsock;
void __fastcall TForm1::StartBTClick(TObject *Sender)
{
struct hostent * he;
struct sockaddr_in addr;
if ((he=gethostbyname("usm.rov"))==NULL)
{
ShowMessage("Error: gethostbyname failed!");
return;
}
if (he->h_addr==NULL)
{
ShowMessage("Error: Host not found!");
return;
}
memset(&addr, 0, sizeof(addr));
memcpy(&(addr.sin_addr.s_addr), he->h_addr, sizeof(addr.sin_addr.s_addr));
addr.sin_port=htons(2000);
addr.sin_family=PF_INET;
if ((ADCsock=socket(PF_INET, SOCK_STREAM, 0))==INVALID_SOCKET)
{
ShowMessage("Error: Can't create socket!");
return;
}
{
DWORD v_ctl=1;
ioctlsocket(ADCsock,FIONBIO,&v_ctl); //Неблокирующийся режим
}
if (connect(ADCsock,(const struct sockaddr *)&addr, sizeof(addr)))
{
int err=WSAGetLastError();
if (err!=WSAEWOULDBLOCK)
{
closesocket(ADCsock);
ShowMessage("Error: Connect failed!");
return;
}
fd_set rfds; //Ожидающие данных (или ответ, или закрытие)
fd_set wfds; //Ожидающие подключения (готовность писать)
fd_set efds; //Ожидающие подключения влетают сюда при ошибке
struct timeval tv;
tv.tv_sec=3; //Дольше 3х секунд не ждем, нефиг
tv.tv_usec=0;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
FD_SET(ADCsock,&wfds);
FD_SET(ADCsock,&efds);
int i=select(0,NULL,&wfds,&efds,&tv);
if (i!=0)
{
if (FD_ISSET(ADCsock,&wfds))
{
//соединились
goto L1;
}
}
//Ахтунг, короче
closesocket(ADCsock);
ShowMessage("Error: Can't connect!");
return;
}
L1:
DWORD br;
fout = CreateFile("adc_data.wav",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0);
WriteFile(fout,wav_hdr,sizeof(wav_hdr),&br,NULL);
total_size=0;
Timer1->Enabled=true;
LblReceivedBytes->Caption="";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopBTClick(TObject *Sender)
{
if (!Timer1->Enabled) return;
Timer1->Enabled=false;
shutdown(ADCsock, SD_BOTH);
closesocket(ADCsock);
DWORD br=0;
if (total_size&4)
{
WriteFile(fout,&br,4,&br,NULL);
}
//WriteFile(fout,RE_ARR,total_bytes,&br,NULL);
SetFilePointer(fout,0x28,NULL,FILE_BEGIN);
WriteFile(fout,&total_size,4,&br,NULL);
SetFilePointer(fout,0x04,NULL,FILE_BEGIN);
total_size+=0x24;
WriteFile(fout,&total_size,4,&br,NULL);
CloseHandle(fout);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ADCsockError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
ShowMessage("Errorcode: "+ErrorCode);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
int l;
String s;
do
{
char p[8192];
l=recv(ADCsock,p,8192,0);
if (l<0)
{
int err=WSAGetLastError();
if (err!=WSAEWOULDBLOCK)
{
s="Error: recv() return error ";
s+=err;
s+="!";
ShowMessage(s);
}
}
else
if (l>0)
{
DWORD br;
WriteFile(fout,p,l,&br,NULL);
total_size+=l;
}
}
while(l>0);
s="Received ";
s+=total_size;
s+="bytes...";
LblReceivedBytes->Caption=s;
}
//---------------------------------------------------------------------------
Тут чтение выполняется по таймеру, дабы не морочиться с ожиданиями и прочим. Можно просто вызывать Timer1Timer в вечном цикле.