
Творец
   
Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант
Репутация: 4 Всего: 329
|
| Код | unit MainUnit;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, winsock, StdCtrls;
type TTCPClientForm = class(TForm) btSend: TButton; edServer: TEdit; Label1: TLabel; mmLog: TMemo; Label2: TLabel; Label3: TLabel; edPort: TEdit; Label4: TLabel; edSendTo: TEdit; mmMessage: TMemo; Label5: TLabel; Label6: TLabel; edFile: TEdit; procedure btSendClick(Sender: TObject); private { Private declarations } sServerListen : TSOCKET; public { Public declarations } end;
const _Code64: string[64]=('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');
var TCPClientForm: TTCPClientForm;
implementation
{$R *.dfm}
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;
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;
function GetLocalHost: string; var sh : array [0..255] of char; begin if gethostname(sh, 255)=0 then Result := StrPas(sh) else Result := ''; end;
procedure SendStr(s:TSocket; str:String); var sRecvBuff : array [0..255] of char; TempStr : AnsiString; begin TempStr:=str+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(s, sRecvBuff, Length(TempStr), 0), 'Send Attachment'); TCPClientForm.mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr))); end;
procedure Base64Send(FileName: string); var afile: File; i: longint; quads: integer; b: array[0..2279] of byte; j,k,l,m:integer; stream:string[76]; begin AssignFile(afile,filename); Reset(afile,1); SendStr(TCPClientForm.sServerListen, '--========sdfgsagg======'); SendStr(TCPClientForm.sServerListen, 'Content-Type: application/octet-stream; name="'+ExtractFileName(FileName)+'"'); SendStr(TCPClientForm.sServerListen, 'Content-Transfer-Encoding: base64'); SendStr(TCPClientForm.sServerListen, 'Content-Disposition: attachment; filename="'+ExtractFileName(FileName)+'"'); SendStr(TCPClientForm.sServerListen, 'Content-Description: attachment'); SendStr(TCPClientForm.sServerListen, ''); stream:=''; quads:=0; j:=Filesize(afile) div 2280; for i:=1 to j do begin BlockRead(afile,b,2280); for m:=0 to 39 do begin for k:=0 to 18 do begin l:=57*m+3*k; stream[quads+1]:=_Code64[(b[l]div 4)+1]; stream[quads+2]:=_Code64[(b[l] mod 4)*16 +(b[l+1] div 16)+1]; stream[quads+3]:=_Code64[(b[l+1] mod 16)*4 +(b[l+2] div 64)+1]; stream[quads+4]:=_Code64[b[l+2] mod 64+1]; Inc(quads,4);
if quads=76 then begin stream[0]:=#76; SendStr(TCPClientForm.sServerListen, stream); quads:=0; end; end; end; end;
j:=(Filesize(afile) mod 2280) div 3;
for i:=1 to j do begin BlockRead(afile,b,3); stream[quads+1]:=_Code64[(b[0]div 4)+1]; stream[quads+2]:=_Code64[(b[0] mod 4)*16 +(b[1] div 16)+1]; stream[quads+3]:=_Code64[(b[1] mod 16)*4 +(b[2] div 64)+1]; stream[quads+4]:=_Code64[b[2] mod 64+1]; Inc(quads,4);
if quads=76 then begin stream[0]:=#76; SendStr(TCPClientForm.sServerListen, stream); quads:=0; end; end;
if (Filesize(afile) mod 3) = 2 then begin BlockRead(afile,b,2); stream[quads+1]:=_Code64[(b[0]div 4)+1]; stream[quads+2]:=_Code64[(b[0] mod 4)*16 +(b[1] div 16)+1]; stream[quads+3]:=_Code64[(b[1] mod 16)*4 +1]; stream[quads+4]:='='; Inc(quads,4); end;
if (Filesize(afile) mod 3) = 1 then begin BlockRead(afile,b,1); stream[quads+1]:=_Code64[(b[0]div 4)+1]; stream[quads+2]:=_Code64[(b[0] mod 4)*16 +1]; stream[quads+3]:='='; stream[quads+4]:='='; Inc(quads,4); end; stream[0]:=Chr(quads);
if quads>0 then SendStr(TCPClientForm.sServerListen, stream);
CloseFile(afile); end;
procedure TTCPClientForm.btSendClick(Sender: TObject); var wData : WSADATA; server_addr : sockaddr_in; sRecvBuff : array [0..255] of char; TempStr : AnsiString; i, iRet : Integer; begin mmLog.Clear;
// Загрузка WinSock if WSAStartup(MAKEWORD(1,1), wData) <> 0 then begin MessageBox(0, 'Не могу загрузить WinSock', 'Ошибка', 0); exit; end;
// Создание сокета sServerListen := socket(PF_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(StrToInt(edPort.Text)); server_addr.sin_addr := LookupName(edServer.Text);
if (connect(sServerListen, server_addr, sizeof(server_addr)) = SOCKET_ERROR) then begin TestWinSockError('Connect'); exit; end;
TestFuncError(recv(sServerListen, sRecvBuff, 1024, 0), 'Ошибка приветствия'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
// Заприветствуем сервер TempStr:='HELO '+GetLocalHost+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send HELO'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка приветствия'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
// Скажем от кого письмецо TempStr:='MAIL FROM:<[email protected]>'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send MAIL FROM'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка адресата'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
// Скажем для кого письмецо TempStr:='RCPT TO:<'+edSendTo.Text+'>'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send MAIL TO'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка получателя'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
// Начало отправки данных TempStr:='DATA'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send DATA'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка начала данных'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
//////////////////// //Заголовок ///////////////////// // Для TempStr:='From:<[email protected]>'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send MAIL FROM'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
// От TempStr:='To:<'+edSendTo.Text+'>'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send MAIL TO'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
// Кодировка SendStr(sServerListen, 'Mime-Version: 1.0'); SendStr(sServerListen, 'Content-Type: multipart/mixed;'); SendStr(sServerListen, ' boundary="========sdfgsagg======"');
SendStr(sServerListen, ''); SendStr(sServerListen, '--========sdfgsagg======'); SendStr(sServerListen, 'Content-Type: text/plain; charset="us-ascii"'); SendStr(sServerListen, '');
//Отправка текста письма for i:=0 to mmMessage.Lines.Count-1 do begin // Сообщение TempStr:=mmMessage.Lines[i]+#13+#10; while TempStr<>'' do begin CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); iRet:=send(sServerListen, sRecvBuff, Length(TempStr), 0);
if iRet=SOCKET_ERROR then break;
mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
Delete(TempStr, 1, iRet); end; end;
//Отправка эттача SendStr(sServerListen, ''); if edFile.Text<>'' then Base64Send(edFile.Text);
// Конец сообщения TempStr:=#13+#10+'.'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send .'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка конца сообщения'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
// Выход TempStr:='QUIT'+#13+#10; CopyMemory(@sRecvBuff, PChar(TempStr), Length(TempStr)); TestFuncError(send(sServerListen, sRecvBuff, Length(TempStr), 0), 'Send QUIT'); mmLog.Lines.Add('>'+Copy(TempStr, 1, Pos(#13, TempStr)));
TestFuncError(recv(sServerListen, sRecvBuff, SizeOf(sRecvBuff), 0), 'Ошибка выхода'); TempStr:=sRecvBuff; mmLog.Lines.Add('<'+Copy(TempStr, 1, Pos(#13, TempStr))); Application.ProcessMessages;
CloseSocket(sServerListen); end;
end.
|
|