//////////////////////////////////////////////////////////////////////////////
// 아래는 소켓과 관련하여 한델 Q/A를 참고하여
// 간단히 만들어본 함수들입니다.
// 아래부분으로 내려가시다보면 질문이있습니다.
//////////////////////////////////////////////////////////////////////////////
unit uXSocket;
interface
uses
windows, messages, sysutils, classes, scktcomp, Dialogs, stdctrls, controls;
const
mtText = $FF00000000000000; // 텍스트
mtData = $FF00000000000001; // 데이타
mtDataEnd = $FF00000000000002; // 데이타전송완료시
mtTransNM = $FF00000000000003; // 전송시파일명
ctText = 'FF00000000000000';
ctData = 'FF00000000000001'; // 데이타
ctDataEnd = 'FF00000000000002'; // 데이타전송완료시
ctTransNM = 'FF00000000000003'; // 전송시파일명
mtLens = 4096;
type
Pekit = record
msgtp : String[16];
dat: array[0..mtLens-1] of char;
end;
Function FrontToBack(vValue: String): String;
Function RPos(Const vSubStr: String; Const vValue: String): Integer;
Function GetMemoLine(memo:TCustomMemo): Integer;
Function GetMemoCol(memo:TCustomMemo): Integer;
Function Memo2Str(sList: TCustomMemo; itemi: Integer): String;
Procedure AddStr(var Vvalue: String; vStr:Array of String);
Function Strings2Str(sList: TStrings; itemi: Integer): String;
function Int2Hex(nFmt: Integer): String;
Function Int642Hex(nFmt: Int64): String;
Function SendData(clSocket: TCustomWinSocket; theData: String; nFmt: int64=mtText): Boolean; overload;
Function SendData(clSocket: TCustomWinSocket; theData: pChar; nFmt: int64): Boolean; overload;
Procedure GetReceiveFile(ssdata : Pekit);
Procedure SetTransMittFile(clSocket: TCustomWinSocket; sPathFile: String);
var
DownLoadFile: Integer;
defaultDownFolder: String;
implementation
Function FrontToBack(vValue: String): String;
var
iz, mLen: Integer;
Begin
mLen := Length(vValue);
SetLength(Result, mLen);
For iz := mLen downto 1 do Result[iz] := vValue[mLen+1-iz];
End;
// 아직완벽하지 않은 루틴임...
Function RPos(Const vSubStr: String; Const vValue: String): Integer;
Begin
Result := pos(vSubStr, FrontToBack(vValue));
if Result > 0 Then Result := Length(vValue)+1-Result;
End;
Function GetMemoLine(memo:TCustomMemo): Integer;
var
LineNum:LongInt;
begin
LineNum:=SendMessage(Memo.Handle, EM_LINEFROMCHAR, Memo.SelStart, 0);
Result := LineNum+1;
end;
Function GetMemoCol(memo:TCustomMemo): Integer;
var
LineNum, CharseBeforeLine:LongInt;
begin
LineNum:=SendMessage(Memo.Handle, EM_LINEFROMCHAR, Memo.SelStart, 0);
CharseBeforeLine := SendMessage(Memo.Handle, EM_LINEINDEX, LineNum, 0);
Result := Memo.SelStart - CharseBeforeLine + 1;
end;
////////////////////////////////
// 32bit 정수형을 16진수 문자열로 치환하는 루틴
Function Int2Hex(nFmt: Integer): String;
var
z: Integer;
u, uh, ul: Byte;
Begin
result := '';
for z := 3 downto 0 do Begin
u := (nFmt shr (z * 8)) and $FF;
uh := (u shr 4) and $F;
ul := u and $F;
if uh >= 10 Then result := Result + Chr(Byte('A')+uh-10)
else result := Result + Chr(Byte('0')+uh);
if ul >= 10 Then result := Result + Chr(Byte('A')+ul-10)
else result := Result + Chr(Byte('0')+ul);
End;
End;
////////////////////////////////
// 64bit 정수형을 16진수 문자열로 치환하는 루틴
Function Int642Hex(nFmt: Int64): String;
var
z: Integer;
u, uh, ul: Byte;
Begin
result := '';
for z := 7 downto 0 do Begin
u := (nFmt shr (z * 8)) and $FF;
uh := (u shr 4) and $F;
ul := u and $F;
if uh >= 10 Then result := Result + Chr(Byte('A')+uh-10)
else result := Result + Chr(Byte('0')+uh);
if ul >= 10 Then result := Result + Chr(Byte('A')+ul-10)
else result := Result + Chr(Byte('0')+ul);
End;
End;
Procedure AddStr(var Vvalue: String; vStr:Array of String);
var
i : Integer;
Begin
For i := Low(vStr) to High(vStr) do Vvalue := VValue + vStr[i];
End;
Function Strings2Str(sList: TStrings; itemi: Integer): String;
var
iz: Integer;
Begin
for iz := itemi to sList.Count-1 do AddStr(Result, [sList.Strings[iz]]);
End;
Function Memo2Str(sList: TCustomMemo; itemi: Integer): String;
var
iz, iu: Integer;
Begin
iu := 0;
if itemi < 0 Then iu := GetMemoLine(sList)
else if itemi >= 0 Then iu := itemi;
for iz := iu to sList.Lines.Count-1 do AddStr(Result, [sList.Lines.Strings[iz]]);
End;
///////////////////////////////////////////////////////////////////////////
//
Function SendData(clSocket: TCustomWinSocket; theData: String; nFmt: int64): Boolean;
var
lvs : TMemoryStream;
p : Pekit;
Begin
lvs := TMemoryStream.Create;
Zeromemory(@p,sizeof(pekit));
p.msgtp := int642Hex(nFmt);
strpcopy(@p.dat, theData);
lvs.Write(p, sizeof(p));
lvs.Position := 0;
Result := clSocket.Sendstream(lvs); // 작업이 끝나면 자동으로 Free되는 것 같음....
end;
Function SendData(clSocket: TCustomWinSocket; theData: pChar; nFmt: int64): Boolean;
var
lvs : TMemoryStream;
p : Pekit;
Begin
lvs := TMemoryStream.Create;
Zeromemory(@p,sizeof(pekit));
p.msgtp := int642Hex(nFmt);
strcopy(@p.dat, theData);
lvs.Write(p, sizeof(p));
lvs.Position := 0;
Result := clSocket.Sendstream(lvs); // 작업이 끝나면 자동으로 Free되는 것 같음....
end;
Procedure GetReceiveFile(ssdata : Pekit);
var
pathandFile: String;
Begin
if ssdata.msgtp = ctTransNM Then Begin
pathandFile := defaultDownFolder + strpas(ssdata.dat);
DownLoadFile := FileCreate(pathandFile);
if DownLoadFile <> -1 Then FileSeek(DownLoadFile, 0, 0);
end
else if ssdata.msgtp = ctData Then Begin
if DownLoadFile = -1 Then Exit;
FileWrite(DownLoadFile, ssdata.dat, sizeof(ssdata.dat));
End
else if ssdata.msgtp = ctDataEnd Then Begin
if DownLoadFile = -1 Then Exit;
FileWrite(DownLoadFile, ssdata.dat, strLen(ssdata.dat));
FileClose(DownLoadFile);
End;
End;
/////////////////////////////////////////////////////////////////////////////////
// 이곳이 질문의요지인데요.....
// 특정 단축키를 누를때 이 프로시져를 호출하고요
// 받는 부분은 GetReceiveFile(ssdata : Pekit) 평션을 이용하여 받습니다.
// 아래소켓이벤트에서 호출하는 식으로요....
// 일단 파일의 전송여부를 파악하기 위하여 보낼때는 파일을 읽어서
// 읽어진 버퍼의 내용을 보내는거죠 일정시간 지나고
// 다시 보내는 식으로요...
// 일단 문자열은 잘전송되고요 아래 전송루틴도 돌아가는것 같은데요....
// 일단 전송되어진 파일의 크기가 일단 크고 그 안에 내용도 부분적으로
// 잘 이상한 자료가 들어가는것 같습니다....
// 글구 파일전송루틴만 콜하면 다돌고나서 에러가 나는것 같구요
// 프로그램 종료시에 에러가 남니다...
////////////////////////////////////////////////////////////////////////////////
//procedure TChatForm.ClientSocketRead(Sender: TObject;
// Socket: TCustomWinSocket);
//var
// ssdata:Pekit;
//begin
// socket.ReceiveBuf(ssdata, sizeof(ssdata));
// if ssdata.msgtp = ctText Then Begin
// Memo2.Lines.Add(strpas(ssdata.dat));
// End
// else if (ssdata.msgtp = ctData) or (ssdata.msgtp = ctDataEnd)
// or (ssdata.msgtp = ctTransNm) Then Begin
// GetReceiveFile(ssdata);
// Memo2.Lines.Add('파일전송중입니다.');
// End;
//end;
//procedure TChatForm.ServerSocketClientRead(Sender: TObject;
// Socket: TCustomWinSocket);
//var
// ssdata:Pekit;
//begin
// socket.ReceiveBuf(ssdata, sizeof(ssdata));
// if ssdata.msgtp = ctText Then Begin
// Memo2.Lines.Add(strpas(ssdata.dat));
// End
// else if (ssdata.msgtp = ctData) or (ssdata.msgtp = ctDataEnd)
// or (ssdata.msgtp = ctTransNm) Then Begin
// GetReceiveFile(ssdata);
// End;
//end;
/////////////////////////////////////////////////////////////////////////////////
Procedure SetTransMittFile(clSocket: TCustomWinSocket; sPathFile: String);
var
ssdata: pekit;
nread: Integer;
ssFileName: String;
Begin
nread := RPos('', sPathFile);
ssFileName := Copy(sPathFile, Length(sPathFile)-nread, Length(sPathFile)-nread);
SendData(clSocket, ssFileName, mtTransNM);
DownLoadFile := FileOpen(sPathFile, fmOpenread or fmShareDenyNone);
if DownLoadFile = -1 Then Exit;
while true do Begin
nread := FileRead(DownLoadFile, ssdata.dat, sizeof(ssdata.dat));
if nread < mtLens Then Begin
SendData(clSocket, @ssdata.dat, mtDataEnd);
FileClose(DownLoadFile);
Exit;
End else SendData(clSocket, @ssdata.dat, mtData);
Sleep(300);
End;
End;
initialization
defaultDownFolder := 'C:';
finalization
end.
////////////////////////////////////////////////////////////////////////////////
// 소켓과 관련하여 고수님들의 답변을 고대합니다.
// 일단 위부분이 어디에 문제가 있는거지 궁금합니다.
안된다고 알고 있습니다.
그래서 인위적으로 특정 크기만큰씩 잘라서 보낸다고 해요..
저도 테스트 해봤는데 역시 그렇더라구요...
도움이 되실련지...
김하늘 wrote:
> //////////////////////////////////////////////////////////////////////////////
> // 아래는 소켓과 관련하여 한델 Q/A를 참고하여
> // 간단히 만들어본 함수들입니다.
> // 아래부분으로 내려가시다보면 질문이있습니다.
> //////////////////////////////////////////////////////////////////////////////
>
> unit uXSocket;
>
> interface
>
> uses
> windows, messages, sysutils, classes, scktcomp, Dialogs, stdctrls, controls;
>
> const
> mtText = $FF00000000000000; // 텍스트
> mtData = $FF00000000000001; // 데이타
> mtDataEnd = $FF00000000000002; // 데이타전송완료시
> mtTransNM = $FF00000000000003; // 전송시파일명
>
>
> ctText = 'FF00000000000000';
> ctData = 'FF00000000000001'; // 데이타
> ctDataEnd = 'FF00000000000002'; // 데이타전송완료시
> ctTransNM = 'FF00000000000003'; // 전송시파일명
> mtLens = 4096;
>
> type
> Pekit = record
> msgtp : String[16];
> dat: array[0..mtLens-1] of char;
> end;
>
> Function FrontToBack(vValue: String): String;
> Function RPos(Const vSubStr: String; Const vValue: String): Integer;
> Function GetMemoLine(memo:TCustomMemo): Integer;
> Function GetMemoCol(memo:TCustomMemo): Integer;
> Function Memo2Str(sList: TCustomMemo; itemi: Integer): String;
> Procedure AddStr(var Vvalue: String; vStr:Array of String);
> Function Strings2Str(sList: TStrings; itemi: Integer): String;
> function Int2Hex(nFmt: Integer): String;
> Function Int642Hex(nFmt: Int64): String;
> Function SendData(clSocket: TCustomWinSocket; theData: String; nFmt: int64=mtText): Boolean; overload;
> Function SendData(clSocket: TCustomWinSocket; theData: pChar; nFmt: int64): Boolean; overload;
> Procedure GetReceiveFile(ssdata : Pekit);
> Procedure SetTransMittFile(clSocket: TCustomWinSocket; sPathFile: String);
>
> var
> DownLoadFile: Integer;
> defaultDownFolder: String;
>
> implementation
>
> Function FrontToBack(vValue: String): String;
> var
> iz, mLen: Integer;
> Begin
> mLen := Length(vValue);
> SetLength(Result, mLen);
> For iz := mLen downto 1 do Result[iz] := vValue[mLen+1-iz];
> End;
>
> // 아직완벽하지 않은 루틴임...
> Function RPos(Const vSubStr: String; Const vValue: String): Integer;
> Begin
> Result := pos(vSubStr, FrontToBack(vValue));
> if Result > 0 Then Result := Length(vValue)+1-Result;
> End;
>
> Function GetMemoLine(memo:TCustomMemo): Integer;
> var
> LineNum:LongInt;
> begin
> LineNum:=SendMessage(Memo.Handle, EM_LINEFROMCHAR, Memo.SelStart, 0);
> Result := LineNum+1;
> end;
>
> Function GetMemoCol(memo:TCustomMemo): Integer;
> var
> LineNum, CharseBeforeLine:LongInt;
> begin
> LineNum:=SendMessage(Memo.Handle, EM_LINEFROMCHAR, Memo.SelStart, 0);
> CharseBeforeLine := SendMessage(Memo.Handle, EM_LINEINDEX, LineNum, 0);
> Result := Memo.SelStart - CharseBeforeLine + 1;
> end;
>
> ////////////////////////////////
> // 32bit 정수형을 16진수 문자열로 치환하는 루틴
> Function Int2Hex(nFmt: Integer): String;
> var
> z: Integer;
> u, uh, ul: Byte;
> Begin
> result := '';
> for z := 3 downto 0 do Begin
> u := (nFmt shr (z * 8)) and $FF;
> uh := (u shr 4) and $F;
> ul := u and $F;
> if uh >= 10 Then result := Result + Chr(Byte('A')+uh-10)
> else result := Result + Chr(Byte('0')+uh);
> if ul >= 10 Then result := Result + Chr(Byte('A')+ul-10)
> else result := Result + Chr(Byte('0')+ul);
> End;
> End;
>
> ////////////////////////////////
> // 64bit 정수형을 16진수 문자열로 치환하는 루틴
> Function Int642Hex(nFmt: Int64): String;
> var
> z: Integer;
> u, uh, ul: Byte;
> Begin
> result := '';
> for z := 7 downto 0 do Begin
> u := (nFmt shr (z * 8)) and $FF;
> uh := (u shr 4) and $F;
> ul := u and $F;
> if uh >= 10 Then result := Result + Chr(Byte('A')+uh-10)
> else result := Result + Chr(Byte('0')+uh);
> if ul >= 10 Then result := Result + Chr(Byte('A')+ul-10)
> else result := Result + Chr(Byte('0')+ul);
> End;
> End;
>
> Procedure AddStr(var Vvalue: String; vStr:Array of String);
> var
> i : Integer;
> Begin
> For i := Low(vStr) to High(vStr) do Vvalue := VValue + vStr[i];
> End;
>
> Function Strings2Str(sList: TStrings; itemi: Integer): String;
> var
> iz: Integer;
> Begin
> for iz := itemi to sList.Count-1 do AddStr(Result, [sList.Strings[iz]]);
> End;
>
> Function Memo2Str(sList: TCustomMemo; itemi: Integer): String;
> var
> iz, iu: Integer;
> Begin
> iu := 0;
> if itemi < 0 Then iu := GetMemoLine(sList)
> else if itemi >= 0 Then iu := itemi;
> for iz := iu to sList.Lines.Count-1 do AddStr(Result, [sList.Lines.Strings[iz]]);
> End;
>
> ///////////////////////////////////////////////////////////////////////////
> //
> Function SendData(clSocket: TCustomWinSocket; theData: String; nFmt: int64): Boolean;
> var
> lvs : TMemoryStream;
> p : Pekit;
> Begin
> lvs := TMemoryStream.Create;
> Zeromemory(@p,sizeof(pekit));
> p.msgtp := int642Hex(nFmt);
> strpcopy(@p.dat, theData);
> lvs.Write(p, sizeof(p));
> lvs.Position := 0;
> Result := clSocket.Sendstream(lvs); // 작업이 끝나면 자동으로 Free되는 것 같음....
> end;
>
> Function SendData(clSocket: TCustomWinSocket; theData: pChar; nFmt: int64): Boolean;
> var
> lvs : TMemoryStream;
> p : Pekit;
> Begin
> lvs := TMemoryStream.Create;
> Zeromemory(@p,sizeof(pekit));
> p.msgtp := int642Hex(nFmt);
> strcopy(@p.dat, theData);
> lvs.Write(p, sizeof(p));
> lvs.Position := 0;
> Result := clSocket.Sendstream(lvs); // 작업이 끝나면 자동으로 Free되는 것 같음....
> end;
>
> Procedure GetReceiveFile(ssdata : Pekit);
> var
> pathandFile: String;
> Begin
> if ssdata.msgtp = ctTransNM Then Begin
> pathandFile := defaultDownFolder + strpas(ssdata.dat);
> DownLoadFile := FileCreate(pathandFile);
> if DownLoadFile <> -1 Then FileSeek(DownLoadFile, 0, 0);
> end
> else if ssdata.msgtp = ctData Then Begin
> if DownLoadFile = -1 Then Exit;
> FileWrite(DownLoadFile, ssdata.dat, sizeof(ssdata.dat));
> End
> else if ssdata.msgtp = ctDataEnd Then Begin
> if DownLoadFile = -1 Then Exit;
> FileWrite(DownLoadFile, ssdata.dat, strLen(ssdata.dat));
> FileClose(DownLoadFile);
> End;
> End;
>
> /////////////////////////////////////////////////////////////////////////////////
> // 이곳이 질문의요지인데요.....
> // 특정 단축키를 누를때 이 프로시져를 호출하고요
> // 받는 부분은 GetReceiveFile(ssdata : Pekit) 평션을 이용하여 받습니다.
> // 아래소켓이벤트에서 호출하는 식으로요....
> // 일단 파일의 전송여부를 파악하기 위하여 보낼때는 파일을 읽어서
> // 읽어진 버퍼의 내용을 보내는거죠 일정시간 지나고
> // 다시 보내는 식으로요...
> // 일단 문자열은 잘전송되고요 아래 전송루틴도 돌아가는것 같은데요....
> // 일단 전송되어진 파일의 크기가 일단 크고 그 안에 내용도 부분적으로
> // 잘 이상한 자료가 들어가는것 같습니다....
> // 글구 파일전송루틴만 콜하면 다돌고나서 에러가 나는것 같구요
> // 프로그램 종료시에 에러가 남니다...
> ////////////////////////////////////////////////////////////////////////////////
> //procedure TChatForm.ClientSocketRead(Sender: TObject;
> // Socket: TCustomWinSocket);
> //var
> // ssdata:Pekit;
> //begin
> // socket.ReceiveBuf(ssdata, sizeof(ssdata));
> // if ssdata.msgtp = ctText Then Begin
> // Memo2.Lines.Add(strpas(ssdata.dat));
> // End
> // else if (ssdata.msgtp = ctData) or (ssdata.msgtp = ctDataEnd)
> // or (ssdata.msgtp = ctTransNm) Then Begin
> // GetReceiveFile(ssdata);
> // Memo2.Lines.Add('파일전송중입니다.');
> // End;
> //end;
>
> //procedure TChatForm.ServerSocketClientRead(Sender: TObject;
> // Socket: TCustomWinSocket);
> //var
> // ssdata:Pekit;
> //begin
> // socket.ReceiveBuf(ssdata, sizeof(ssdata));
> // if ssdata.msgtp = ctText Then Begin
> // Memo2.Lines.Add(strpas(ssdata.dat));
> // End
> // else if (ssdata.msgtp = ctData) or (ssdata.msgtp = ctDataEnd)
> // or (ssdata.msgtp = ctTransNm) Then Begin
> // GetReceiveFile(ssdata);
> // End;
> //end;
> /////////////////////////////////////////////////////////////////////////////////
> Procedure SetTransMittFile(clSocket: TCustomWinSocket; sPathFile: String);
> var
> ssdata: pekit;
> nread: Integer;
> ssFileName: String;
> Begin
> nread := RPos('', sPathFile);
> ssFileName := Copy(sPathFile, Length(sPathFile)-nread, Length(sPathFile)-nread);
> SendData(clSocket, ssFileName, mtTransNM);
> DownLoadFile := FileOpen(sPathFile, fmOpenread or fmShareDenyNone);
> if DownLoadFile = -1 Then Exit;
> while true do Begin
> nread := FileRead(DownLoadFile, ssdata.dat, sizeof(ssdata.dat));
> if nread < mtLens Then Begin
> SendData(clSocket, @ssdata.dat, mtDataEnd);
> FileClose(DownLoadFile);
> Exit;
> End else SendData(clSocket, @ssdata.dat, mtData);
> Sleep(300);
> End;
> End;
>
> initialization
> defaultDownFolder := 'C:';
> finalization
> end.
>
> ////////////////////////////////////////////////////////////////////////////////
> // 소켓과 관련하여 고수님들의 답변을 고대합니다.
> // 일단 위부분이 어디에 문제가 있는거지 궁금합니다.
>