[요약] Winsock 애플리케이션을 작성한 프로그래머는 Winsock 애플리케이션 작성이 결코 쉬운 작업이 아니라는 것을 알고 있습니다. 다행히도 Delphi4의 Tclientsocket 및 Tserversocket은 Windows의 관련 API를 캡슐화하여 액세스를 크게 단순화합니다. Winsock에 추가하면 Winsock 응용 프로그램을 매우 쉽게 작성할 수 있습니다. 이 기사에서는 LAN에 있는 다른 컴퓨터의 화면을 읽는 예제를 통해 Delphi를 사용하여 Winsock 애플리케이션을 작성하는 방법을 소개합니다.
직장에서 네트워크 관리자로 일해본 사람이라면 누구나 이런 경험을 했을 것이다. 전화로 다른 사람에게 "원격 제어"를 지시하는 것이 얼마나 짜증나는 일인가. 게다가 나는 게으른 사람이고 도망치고 싶지 않다. 사소한 일로 매일 건물 꼭대기부터 건물 바닥까지, 어떻게 해야 할까요? 다른 컴퓨터의 화면을 읽는 프로그램을 작성해 보는 것은 어떨까요? 훨씬 더 직관적입니다. LAN 내에서 통신하려면 Winsock을 사용하는 것이 가장 좋습니다. Winsock 응용 프로그램을 작성한 프로그래머는 Winsock 응용 프로그램을 작성하는 것이 결코 쉬운 작업이 아니라는 것을 알고 있습니다. Winsock에서 복잡한 API를 직접 다루면 안 됩니다. , Delphi4의 Tclientsocket 및 Tserversocket은 Windows에서 관련 API를 캡슐화하여 Winsock에 대한 액세스를 크게 단순화하여 Winsock 애플리케이션을 매우 쉽게 작성할 수 있습니다. 그럼에도 불구하고 Winsock에 대해 어느 정도 이해하는 것이 가장 좋습니다. 여기서는 자세한 내용을 다루지 않고 직접 읽어보실 수 있습니다.
네트워크를 통해 데이터를 전송하려면 클라이언트 측과 서버 측에 각각 하나씩 최소한 한 쌍의 소켓이 필요합니다. 클라이언트 측 소켓과 서버 측 소켓이 연결되면 서로 통신할 수 있습니다. 소켓은 Tcp/IP 기반으로 설정되며 ipx/spx 및 기타 관련 프로토콜도 지원합니다. Delphi에서는 Tclientsocket과 Tserversocket을 사용하여 클라이언트와 서버 소켓 간의 연결과 통신을 제어합니다. 이 두 구성 요소는 서버와 클라이언트 간의 연결을 관리하는 데 사용되며 소켓 개체 자체가 아닙니다. 소켓 개체를 제어하는 것은 Tclientwinsocket, Tserverclientwinsocket 및 Tserverwinsocket과 같은 TcustomwinSocket입니다.
1. Tclientsocket 구성요소:
Tclientsocket을 양식에 추가하면 응용 프로그램은 Tcp/ip 클라이언트가 되고 Tclientsocket을 사용하여 클라이언트의 Socket 개체를 조작할 수 있습니다.
서버에 대한 연결을 설정하려면 먼저 연결하려는 서버를 지정합니다. 서버를 지정하는 방법에는 두 가지가 있습니다. 하나는 http://www.inPRise.com 또는 LAN의 시스템 이름과 같이 서버의 호스트 이름을 지정하기 위해 Host 속성을 설정하는 것입니다. 약간 더 빠른 도메인 이름 확인이 필요합니다. 또 다른 방법은 Adress 속성을 설정하여 130.0.1.1과 같은 호스트의 IP 주소를 지정하는 것입니다. 두 가지 방법은 동일하지만 Host와 Adress가 모두 설정된 경우 Delphi는 Host 속성만 사용합니다.
그런 다음 서버에 연결하기 위해 포트 번호를 지정해야 합니다. 하나는 기본 포트 번호를 사용하도록 서비스를 설정하는 것입니다. 다른 하나는 1024 이하의 포트 번호를 직접 설정하는 것입니다. , FTP 등 많은 포트가 할당되었습니다. 포트는 20과 21, SMTP 포트는 25, WEB 서버 포트는 80 등입니다. 의도하지 않은 충돌을 방지하려면 자신의 응용 프로그램을 프로그래밍할 때 권장됩니다. 포트를 1024 이상으로 설정하는 것이 가장 좋습니다. 서비스와 포트가 동시에 설정되면 Delphi는 기본 포트인 서비스를 사용합니다.
서버와 포트 번호를 지정한 후 open 메소드를 호출하거나 Active 속성을 True로 설정합니다. 클라이언트의 소켓은 서버의 소켓에 연결 요청을 합니다. 이때 서버가 수신 대기 상태이면 자동으로 수락됩니다. 연결 설정을 요청하면 해당 Onconnet 이벤트가 트리거됩니다. 연결을 끊어야 하는 경우에는 close 메소드를 호출하거나 Active 속성을 False로 설정하기만 하면 됩니다. 이때 ondisconnet 이벤트가 발생합니다.
2. Tserversocket 구성요소:
Tclientsocket과 마찬가지로 서버를 구축하려면 양식에 Tserversock 구성 요소만 배치하면 됩니다.
서버측 소켓 개체는 관리하기가 더 복잡합니다. 서버가 Listening 상태에 있을 때 서버의 소켓 개체는 Tserversocket에 의해 조작되며, 클라이언트가 요청하면 서버는 요청에 응답하고 연결을 설정합니다. 이때 Tserverclientwinsocket을 사용하여 서버 간의 연결을 조작합니다. 소켓 및 클라이언트의 소켓입니다.
서버를 Listening 상태로 만들려면 먼저 포트 번호를 지정해야 합니다. 물론 클라이언트의 포트 번호와 동일해야 합니다. 그런 다음 open 메소드를 호출하거나 Active 속성을 True로 설정합니다.
3. 커뮤니케이션:
클라이언트와 서버 간의 연결이 설정되면 서로 통신이 시작될 수 있습니다. Delphi는 Tserversocket 및 Tclientsocket에 대한 여러 통신 방법을 제공합니다. Sendtext는 텍스트 정보를 보내는 데 사용되고, sendstream은 스트림을 보내는 데 사용되며, SendBuf는 지정된 길이의 데이터를 보내는 데 사용됩니다.
Windows의 기본 버퍼 크기는 4K이므로 4K보다 긴 정보(예: 서버에서 클라이언트로 전송되는 바이너리 스트림)를 보낼 때는 서버에서 Socket.SendStream()만 사용하면 됩니다. , 그러나 클라이언트에서는 다릅니다. 이는 onread 이벤트를 여러 번 트리거하며 Delphi는 "onreadend"와 같은 이벤트를 정의하지 않습니다. 따라서 프로그래머는 데이터를 수신할 때 직접 조립해야 합니다. 이 글에서 채택한 방법은 먼저 스트림 길이를 클라이언트에 보낸 다음 클라이언트가 수신한 데이터를 스트림에 쓰는 것입니다. 클라이언트가 수신을 완료했다는 것입니다. 서버의 경우 sendstream 매개변수로 사용되는 스트림은 소켓에 의해 "소유"됩니다. 소켓 개체가 끝나면 소켓 개체도 종료됩니다. 그렇지 않으면 예외가 발생합니다.
마찬가지로 전송된 텍스트가 4K 미만인 경우, 예를 들어 클라이언트 프로그램에서 다음 호출을 하는 경우
클라이언트소켓1.소켓.SendText('gets');
클라이언트소켓1.소켓.SendText('gets');
클라이언트소켓1.소켓.SendText('gets');
서버가 수신하면 getgets와 같은 현상이 나타납니다. 이는 버퍼에 있는 데이터가 아직 전송되지 않은 경우 새로운 텍스트가 버퍼에 들어가고 컴퓨터가 이를 동일한 데이터 배치로 처리하여 처리하기 때문일 수 있습니다. . 이러한 현상이 발생하지 않도록 하려면 프로그램에서 "공을 앞뒤로 던지는" 방법을 사용할 수 있습니다.
클라이언트 서버
클라이언트소켓1.소켓.SendText('데이터1') 소켓.ReceiveText;
소켓.sendtext('확인');
소켓.수신텍스트;
클라이언트소켓1.소켓.SendText('데이터2')
소켓.ReceiveText;
소켓.sendtext('끝');
소켓.수신텍스트;
다른 컴퓨터에서 서버 프로그램을 실행한 후 클라이언트 프로그램의 텍스트 상자에 컴퓨터 이름을 입력하고 "연결"을 클릭한 후 "사진 가져오기"를 클릭하면 상대방 컴퓨터의 화면이 선명하게 보입니다. 다음은 프로그램의 전체 소스 코드입니다. 이 프로그램은 NT4.0, Win95, Win98, LAN에서 실행될 수 있습니다. 물론 Windows에는 TCP/IP 프로토콜이 설치되어 있어야 하며 IP가 동적으로 할당되거나 지정되어 있어야 합니다. 주소.
시청 중에 "명령"하는 것이 번거롭다면 image1의 키보드 및 마우스 이벤트를 분석한 다음 서버에서 이를 수신한 후 다시 동일한 작업을 수행하므로 사용자는 이를 수행할 수 있습니다. 걱정하지 마세요. Delphi의 Tclientsocket 및 Tserversocket을 사용하면 파일 복사, 온라인 채팅, ICQ 등과 같은 애플리케이션 개발도 완료할 수 있습니다. 구현이 매우 간단하여 자유롭게 상상력을 발휘하여 더욱 매력적인 프로그램을 작성할 수 있습니다.
클라이언트 프로그램:
단위 cmain;
인터페이스
용도
Windows, 메시지, SysUtils, 클래스, 그래픽, 컨트롤, 양식, 대화 상자,
ScktComp, StdCtrls, ExtCtrls,jpeg;
유형
TForm1 = 클래스(TForm)
패널1: T패널;
ScrollBox1: TScrollBox;
이미지1: T이미지;
버튼1: T버튼;
편집1: T편집;
Button2: T버튼;
ClientSocket1: TClientSocket;
라벨1: TLabel;
절차 Button1Click(Sender: TObject);
절차 Button2Click(보내는 사람: TObject);
프로시저 ClientSocket1Connect(Sender: TObject;
소켓: TCustomWinSocket);
절차 ClientSocket1Error(발신자: TObject; 소켓: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: 정수);
절차 ClientSocket1Read(Sender: TObject; 소켓: TCustomWinSocket);
절차 FormCreate(보내는 사람: TObject);
절차 FormClose(Sender: TObject; var Action: TCloseAction);
사적인
{비공개 선언}
공공의
{공개 선언}
끝;
var
Form1: TForm1;
c:롱린트;
m:tmemorystream;
구현
{$R *.DFM}
절차 TForm1.Button1Click(Sender: TObject);
시작하다
노력하다
클라이언트소켓1.닫기;
클라이언트소켓1.호스트:=edit1.text;
clientsocket1.Open; //서버에 연결
제외하고
showmessage(edit1.text+#13#10+'컴퓨터 전원이 켜지지 않거나 서비스 프로그램이 설치되지 않았습니다.');
끝;
끝;
절차 TForm1.Button2Click(Sender: TObject);
시작하다
clientocket1.Socket.SendText('gets'); //화면 이미지가 필요하다는 것을 서버에 알리는 요청을 보냅니다.
끝;
절차 TForm1.ClientSocket1Connect(Sender: TObject;
소켓: TCustomWinSocket);
시작하다
caption:='연결 대상'+edit1.text;
끝;
프로시저 TForm1.ClientSocket1Error(Sender: TObject;
소켓: TCustomWinSocket: TErrorEvent;
varErrorCode: 정수);
시작하다
caption:='연결'+edit1.text+'실패';
showmessage(edit1.text+#13#10+'컴퓨터 전원이 켜지지 않거나 서비스 프로그램이 설치되지 않았습니다.');
오류코드:=0;
끝;
프로시저 TForm1.ClientSocket1Read(Sender: TObject;
소켓: TCustomWinSocket);
var
버퍼:바이트 배열 [0..10000] //수신 버퍼 설정;
len:정수;
ll:문자열;
b:t비트맵;
j:tjpeg이미지;
시작하다
c=0이면 //C는 서버에서 보낸 바이트 수입니다. 0이면 이미지 수신이 아직 시작되지 않았음을 의미합니다.
시작하다
ll:=socket.ReceiveText;
c:=strtoint(ll); // 수신할 바이트 수를 설정합니다.
clientocket1.Socket.SendText('okok'); //이미지 전송을 시작하도록 서버에 알립니다.
다른 끝
start //다음은 이미지 데이터 수신 부분입니다.
len:=socket.ReceiveLength; //패킷 길이를 읽습니다.
소켓.ReceiveBuf(buffer,len); //데이터 패킷을 수신하여 버퍼로 읽습니다.
m.Write(buffer,len); //스트림 M에 추가
if m.Size>=c then //스트림 길이가 수신할 바이트 수보다 크면 수신이 완료됩니다.
시작하다
m.위치:=0;
b:=tbitmap.Create;
j:=tjpegimage.Create;
노력하다
j.LoadFromStream(m); //스트림 M의 데이터를 JPG 이미지 객체 J로 읽습니다.
b.Assign(j); //JPG를 BMP로 변환
Image1.Picture.Bitmap.Assign(b); //image1 요소에 할당
finally //다음은 정리 작업입니다.
b. 무료;
j.무료;
클라이언트소켓1.활성:=false;
클라이언트소켓1.활성:=true;
m.맑음;
c:=0;
끝;
끝;
끝;
끝;
절차 TForm1.FormCreate(Sender: TObject);
시작하다
m:=tmemorystream.Create;
끝;
절차 TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
시작하다
m.free;
ClientSocket1.Close;
끝;
끝.
서버 프로그램:
단위 스메인;
인터페이스
용도
Windows, 메시지, SysUtils, 클래스, 그래픽, 컨트롤, 양식, 대화 상자,
ScktComp,jpeg;
유형
TForm1 = 클래스(TForm)
서버소켓1: TServerSocket;
프로시저 ServerSocket1ClientRead(Sender: TObject;
소켓: TCustomWinSocket);
절차 FormCreate(보내는 사람: TObject);
사적인
{비공개 선언}
공공의
{공개 선언}
끝;
var
Form1: TForm1;
m1:tmemorystream;
구현
{$R *.DFM}
프로시저 TForm1.ServerSocket1ClientRead(Sender: TObject;
소켓: TCustomWinSocket);
var
s,s1:문자열;
책상:t캔버스;
비트맵:tbitmap;
jpg:tjpeg이미지;
시작하다
s:=socket.ReceiveText;
if s='gets' then //클라이언트가 요청을 발행합니다.
시작하다
비트맵:=tbitmap.Create;
jpg:=tjpegimage.Create;
Desk:=tcanvas.Create; //다음 코드는 현재 화면 이미지를 가져오는 것입니다.
Desk.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create; //sendstream(m1)을 사용하여 스트림을 보낸 후 스트림 m1을 초기화합니다.
//소켓 대화가 끝날 때까지 유지됩니다.
//수동으로 해제할 수 없습니다. 그렇지 않으면 예외가 발생합니다.
비트맵으로
시작하다
너비:=화면.너비;
높이:=화면.높이;
canvas.CopyRect(canvas.clipdirect,desk,desk.clipdirect);
끝;
jpg.Assign(bitmap); //이미지를 JPG 형식으로 변환
jpg.SaveToStream(m1); // 스트림에 JPG 이미지 쓰기
jpg.무료;
m1.위치:=0;
s1:=inttostr(m1.size);
Socket.sendtext(s1); //이미지 크기 보내기
끝;
if s='okok'이면 //클라이언트가 이미지를 수신할 준비가 되었습니다.
시작하다
m1.위치:=0;
Socket.SendStream(m1); //JPG 이미지 보내기
끝;
끝;
절차 TForm1.FormCreate(Sender: TObject);
시작하다
ServerSocket1.open;
끝;
끝.