[Аннотация] Программисты, писавшие приложения Winsock, знают, что написание приложений Winsock — задача непростая. Вам не придется напрямую иметь дело со сложными API-интерфейсами Winsock. К счастью, Tclientsocket и Tserversocket в Delphi4 инкапсулируют соответствующие API-интерфейсы в Windows, которые значительно упрощают доступ. в Winsock, что позволяет нам очень легко писать приложения Winsock. В этой статье рассказывается, как писать приложения Winsock с использованием Delphi, на примере чтения экрана другого компьютера в локальной сети.
Любой, кто работал сетевым администратором на рабочем месте, возможно, сталкивался с таким опытом. Как раздражает других, чтобы они работали с помощью «дистанционного управления» по телефону. Более того, я ленивый человек и не хочу бежать от него. каждый день с верха здания вниз по пустяковым делам, что делать? Как насчет написания программы, читающей экран другого компьютера? Это гораздо более интуитивно понятно. Для связи внутри локальной сети лучше всего, конечно, использовать Winsock. Программисты, писавшие приложения Winsock, знают, что написание приложений Winsock ни в коем случае не является легкой задачей. К счастью, вам не придется напрямую иметь дело со сложными API-интерфейсами Winsock. Tclientsocket и Tserversocket в Delphi4 инкапсулируют соответствующие API в Windows, значительно упрощая доступ к Winsock и позволяя нам очень легко писать приложения Winsock. Тем не менее, лучше иметь некоторое представление о Winsock. Я не буду здесь вдаваться в подробности. Вы можете найти несколько книг и прочитать их самостоятельно.
Для передачи данных по сети вам понадобится как минимум пара сокетов: один на стороне клиента, а другой на стороне сервера. Как только сокеты на стороне клиента и сервера соединены, они могут взаимодействовать друг с другом. Сокет установлен на Tcp/ На основе ip, он также поддерживает ipx/spx и другие родственные протоколы. В Delphi Tclientsocket и Tserversocket используются для управления соединением и связью между клиентом и серверным сокетом. Следует отметить, что эти два компонента используются для управления соединением между сервером и клиентом. Они сами по себе не являются объектами Socket. Объектом Socket управляет TcustomwinSocket, например Tclientwinsocket, Tserverclientwinsocket и Tserverwinsocket.
1. Компонент Tclientsocket:
Добавляя Tclientsocket в форму, приложение становится клиентом Tcp/ip, и Tclientsocket можно использовать для управления клиентским объектом Socket.
Чтобы установить соединение с сервером, вы сначала указываете сервер, к которому хотите подключиться. Существует два способа указать сервер. Один из них — установить атрибут Host, чтобы указать имя хоста сервера, например http://www.inPRise.com, или имя компьютера в локальной сети. Этот метод интуитивно понятен. требуется разрешение доменного имени, что будет немного медленнее. Другой метод — установить атрибут Adress для указания IP-адреса хоста, например 130.0.1.1. Эти два метода эквивалентны, но если установлены и 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 в форме.
Объектом сокета на стороне сервера управлять сложнее. Когда сервер находится в состоянии прослушивания, объектом сокета сервера управляет Tserversocket; когда клиент делает запрос, сервер отвечает на запрос и устанавливает соединение. В это время Tserverclientwinsocket используется для управления соединением между сервером. Сокет и клиентский сокет.
Чтобы перевести сервер в состояние прослушивания, необходимо сначала указать номер порта. Конечно, он должен совпадать с номером порта клиента. Затем вызовите метод open или установите для свойства Active значение True.
3. Общение:
Как только соединение между клиентом и сервером установлено, можно начать общение друг с другом. Delphi предоставляет несколько методов связи для Tserversocket, а Tclientsocket используется для отправки текстовой информации, sendstream используется для отправки потоков, а SendBuf используется для отправки данных указанной длины.
Следует отметить, что поскольку размер буфера Windows по умолчанию составляет 4 КБ, при отправке информации длиной более 4 КБ, например, бинарного потока, отправляемого с сервера клиенту, вам нужно использовать только Socket.SendStream() на сервере. , но на клиенте все по-другому. Оно вызывает событие onread несколько раз, а Delphi не определяет такие события, как «onreadend». Поэтому программист должен сам собирать данные при получении. Метод, принятый в этой статье, заключается в том, чтобы сначала отправить длину потока клиенту, а затем отправить поток. Клиент записывает полученные данные в поток. Когда длина потока равна длине, отправленной обратно сервером, это указывает. что клиент завершил его получение. Для сервера поток, используемый в качестве параметра sendstream, будет «принадлежать» объекту Socket. Когда объект Socket завершится, он также завершится. Не освобождайте его самостоятельно, иначе будет вызвано исключение.
Аналогично, когда отправленный текст меньше 4K, например, при следующем вызове в клиентской программе
clientsocket1.Socket.SendText('получает');
clientsocket1.Socket.SendText('получает');
clientsocket1.Socket.SendText('получает');
Когда сервер получает данные, появляются такие явления, как getgets. Это может быть связано с тем, что, когда данные в буфере еще не отправлены, новый текст помещается в буфер, и компьютер обрабатывает его как тот же пакет данных для обработки. . Чтобы этого явления не произошло, можно использовать в программе прием «перебрасывания мяча» вперед-назад:
клиент-сервер
clientocket1.Socket.SendText('data1') socket.ReceiveText;
сокет.sendtext('ок');
сокет.получитьтекст;
clientsocket1.Socket.SendText('data2')
сокет.ReceiveText;
сокет.sendtext('конец');
сокет.получитьтекст;
После запуска серверной программы на другом компьютере введите имя компьютера в текстовое поле клиентской программы, нажмите «Подключиться» и нажмите «Получить изображение». Вы сможете четко видеть экран компьютера другой стороны. Ниже приведен полный исходный код программы. Эта программа может работать в NT4.0, Win95, Win98 и локальной сети. Конечно, в Windows должен быть установлен протокол TCP/IP и должен быть динамически назначен или указан IP-адрес. адрес.
Если вам сложно «командовать» во время просмотра, вы также можете проанализировать события клавиатуры и мыши на изображении 1, а затем отправить их на сервер. После того, как сервер получит его, он снова выполнит ту же операцию, чтобы вы не сделали этого. Оператору не стоит волноваться. Используя Tclientsocket и Tserversocket Delphi, вы также можете завершить разработку таких приложений, как копирование файлов, онлайн-чат, ICQ и т. д. Это очень просто реализовать. Вы можете свободно использовать свое воображение для написания более привлекательных программ.
Клиентская программа:
модуль cmain;
интерфейс
использует
Windows, сообщения, SysUtils, классы, графика, элементы управления, формы, диалоги,
ScktComp, StdCtrls, ExtCtrls, JPEG;
тип
ТФорм1 = класс (ТФорма)
Панель1: ТПанель;
Прокрутка1: TScrollBox;
Изображение1: TImage;
Кнопка1: Кнопка T;
Edit1: TEdit;
Кнопка2: Кнопка T;
КлиентСокет1: ТКлиентСокет;
Метка1: TLabel;
процедура Button1Click (Отправитель: TObject);
процедура Button2Click (Отправитель: TObject);
процедура ClientSocket1Connect (Отправитель: TObject;
Сокет: TCustomWinSocket);
процедура ClientSocket1Error (Отправитель: TObject; Сокет: TCustomWinSocket;
ErrorEvent: TErrorEvent; вар ErrorCode: Integer);
процедура ClientSocket1Read (Отправитель: TObject; Сокет: TCustomWinSocket);
процедура FormCreate (Отправитель: TObject);
процедура FormClose (Отправитель: TObject; вар Действие: TCloseAction);
частный
{Частные заявления}
общественный
{Публичные заявления}
конец;
вар
Форма1: ТФорм1;
с: лонгинт;
м: тмемористрим;
выполнение
{$R *.DFM}
процедура TForm1.Button1Click(Отправитель: TObject);
начинать
пытаться
clientsocket1.Close;
clientsocket1.Host:=edit1.text;
clientsocket1.Open; //Подключаемся к серверу
кроме
showmessage(edit1.text+#13#10+'Компьютер не включен или сервисная программа не установлена');
конец;
конец;
процедура TForm1.Button2Click(Отправитель: TObject);
начинать
clientsocket1.Socket.SendText('gets'); //Отправляем запрос на уведомление сервера о необходимости изображения экрана
конец;
процедура TForm1.ClientSocket1Connect(Отправитель: TObject;
Сокет: TCustomWinSocket);
начинать
caption:='Подключиться к'+edit1.text;
конец;
процедура TForm1.ClientSocket1Error(Отправитель: TObject;
Сокет: TCustomWinSocket;ErrorEvent: TErrorEvent;
varErrorCode: Целое число);
начинать
caption:='Connection'+edit1.text+'Failed';
showmessage(edit1.text+#13#10+'Компьютер не включен или сервисная программа не установлена');
код ошибки:=0;
конец;
процедура TForm1.ClientSocket1Read(Отправитель: TObject;
Сокет: TCustomWinSocket);
вар
buffer:array [0..10000] байт //Установка буфера приема;
длина: целое число;
ll: строка;
б: tbitmap;
j: tjpegimage;
начинать
если c=0, то //C — количество байт, отправленных сервером. Если оно равно 0, это означает, что прием изображения еще не начался.
начинать
ll:=socket.ReceiveText;
c:=strtoint(ll); //Устанавливаем количество принимаемых байтов
clientsocket1.Socket.SendText('okok'); //Уведомляем сервер о начале отправки изображений
закончить еще
начало //Ниже приведена часть приема данных изображения
len:=socket.ReceiveLength; //Читаем длину пакета
socket.ReceiveBuf(buffer,len); //Получаем пакет данных и читаем его в буфер
m.Write(buffer,len); //Добавить в поток M
if m.Size>=c then //Если длина потока больше количества принимаемых байт, прием завершается
начинать
м.Позиция:=0;
б:=tbitmap.Create;
j:=tjpegimage.Create;
пытаться
j.LoadFromStream(m); //Считаем данные из потока M в объект изображения JPG J
b.Assign(j); //Конвертируем JPG в BMP;
Image1.Picture.Bitmap.Assign(b); //Назначаем элементу image1
наконец //Далее идет работа по очистке
б.бесплатно;
j.бесплатно;
clientsocket1.Active:=false;
clientsocket1.Active:=true;
м. Ясно;
с:=0;
конец;
конец;
конец;
конец;
процедура TForm1.FormCreate(Отправитель: TObject);
начинать
м:=tmemorystream.Create;
конец;
процедура TForm1.FormClose(Отправитель: TObject; var Action: TCloseAction);
начинать
м.свободно;
ClientSocket1.Закрыть;
конец;
конец.
Серверная программа:
единица измерения;
интерфейс
использует
Windows, сообщения, SysUtils, классы, графика, элементы управления, формы, диалоги,
ScktComp, JPEG;
тип
ТФорм1 = класс (ТФорма)
СерверСокет1: ТСерверСокет;
процедура ServerSocket1ClientRead (Отправитель: TObject;
Сокет: TCustomWinSocket);
процедура FormCreate (Отправитель: TObject);
частный
{Частные заявления}
общественный
{Публичные заявления}
конец;
вар
Форма1: ТФорм1;
m1:tmemorystream;
выполнение
{$R *.DFM}
процедура TForm1.ServerSocket1ClientRead(Отправитель: TObject;
Сокет: TCustomWinSocket);
вар
с, с1:строка;
стол: холст;
растровое изображение: tbitmap;
jpg:tjpegimage;
начинать
s:=socket.ReceiveText;
if s='gets' then //Клиент отправляет запрос
начинать
растровое изображение:=tbitmap.Create;
jpg:=tjpegimage.Create;
desk:=tcanvas.Create //Следующий код предназначен для получения текущего изображения экрана
рабочий стол.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create; //Инициализируем поток m1 после отправки потока с помощью sendstream(m1),
//Оно будет оставаться до тех пор, пока не закончится диалог сокета,
//Невозможно освободить вручную, иначе будет вызвано исключение
с растровым изображением сделать
начинать
ширина:=экран.Ширина;
высота:=экран.Высота;
холст.CopyRect(canvas.cliprect,desk,desk.cliprect);
конец;
jpg.Assign(bitmap); //Преобразуем изображение в формат JPG.
jpg.SaveToStream(m1); //Записываем изображение JPG в поток
JPG.бесплатно;
m1.Позиция:=0;
s1:=inttostr(m1.size);
Socket.sendtext(s1); //Отправляем размер изображения
конец;
if s='okok' then //Клиент готов получать изображения
начинать
m1.Позиция:=0;
Socket.SendStream(m1); //Отправляем изображение в формате JPG;
конец;
конец;
процедура TForm1.FormCreate(Отправитель: TObject);
начинать
СерверSocket1.open;
конец;
конец.