Ну вот господа, сегодня я расскажу о такой замечательной вещи как UDP. Это в свою очередь протокол который предназначен для обмена данными (дейтограмм) в сети, является одним из самых быстрых (именно этот протокол используется для видеоконференций в таком известном клиенте как MSN, да и во многих других).
USER DATAGRAM PROTOCOL – интерфейс пользовательских дейтограмм. Не гарантирует стопроцентную доставку сообщений, возможна частичная, или полная потеря данных, именно негарантированость доставки сообщений дает высокую скорость.
Лично на своём опыте никогда не сталкивался с потерей данных , ни с частичной, ни с полной. Данные всегда приходили в целостности и сохранности, независимо от размера пакета.
ВНИМАНИЕ (порты от 1 до 1024 являются системными, и их использование затруднит вашу задачу, особенно в сетевых играх, где пакеты передаются непрерывно) Порты от 1024 до 49151 являются зарезервированными, и тоже лучше не использовать. Порты от 49151 до 65535 они динамические, т.е. лучше использовать их.
Давайте создадим простую программу которая будет подсоединятся к какому-либо компьютеру, и обмениваться сообщениями с ним.
Итак, разберемся поподробнее на примере.
Это начало основной программы:
Graphics 640,480,0,2 SetBuffer BackBuffer ()
Создадим поток на своём компьютере с помощью следующей команды, на порту 50345
Stream=CreateUDPStream (50345)
Вы наверное поняли что в скобках указывается порт.
Можно также порт не указывать, и программа выберет нужный порт, т.е. это выглядело бы так:
Stream=CreateUDPStream ()
If Stream = 0 Then Print “Stream doesn’t exist ! Press any key to continue…” WaitKey () End Endif
Начиная со слова IF я думаю всем понятно что делает программа, для тех кому непонятно объясню:
Если поток равен нулю (т.е. если он не существует, если он не создан, т.е. программа по каким либо причинам его не смогла создать, то выводим текст “поток не существует, нажмите любую клавишу….”, если нажата какая-либо клавиша, выходим из программы).
Ну вот, что дальше? А дальше всё просто!
DestIP$=Input(“Destination IP ”) DestPort=Input(“Destination Port ”)
Скажу сразу что UDP протокол не работает с IP в точечном виде, т.е. типа ххх.ххх.ххх.ххх, а с целочисленным IP, т.е. IP представляется в виде числа.
Чтобы превратить IP из точечного в целочисленный, нужно использовать вот эту функцию:
Function Int_IP(IP$) d1%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,".")) d2%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-In str(IP$,".")) d3%=Left(IP$,Instr(IP$,".")-1):IP$=Right(IP$,Len(IP$)-Instr(IP$,".")) d4%=IP$ Return (d1 Shl 24) + (d2 Shl 16) + (d3 Shl 8 ) +d4 End Function
Программа предложит ввести сначала IP, (т.е. IP того компьютера к которому мы хотим подсоединится), затем порт того же компьютера.
Давайте теперь сделаем так: Если эта же программа запущена на компьютере к которому подсоединяемся, то выведем на экран сообщение Пользователь в онлайне
Сдесь мы просто вычесляем свой IP
C=CountHostIps("") _Ip$=DottedIP(HostIP( c ) )
Пишем сообщение
WriteLine Stream,”User “ + _Ip$+ “ is OnLine!” SendUDPMsg Stream,Int_IP(DestIP$),DestPort
Итак, что мы сделали? Мы сначала его записали в поток, и затем из этого потока послали сообщение на IP (тот который вы ввели ранее), и тому порту (который вы также ввели ранее).
Вы спросите – «Ну послали мы сообщение, и как мы знаем в сети он или нет?» Ответ – «Да очень просто!»
Давайте допустим, что сообщение находящийся в сети человек получил, что программа должна сделать? Я думаю что отослать ответное сообщение Ну давайте напишем код:
Delay 1000 If RecvUDPMsg (Stream) Then On$=ReadLine (stream) If On$=”Online” Print “User is Online” Else Print “User is OffLine” Endif Endif
Такс, значит считываем строку, и сохраняем в переменную On$. Delay вначале служит для того чтобы наш клиент (или сервер) «успел» получить и отправить ответное сообщение (хотя 1 сек. я взял с большим запасом).
(Программа, которая запущена на подсоединяемом компьютере немножко должна отличатся, а именно портами, и ответом на Online/Offline, вы не получите никакого сообщения если порты у сервера и клиента будут одинаковы, но это касается только локальных сетей)
Так идем дальше:
Начинается главный цикл Repeat:
Скажу сразу, я буду использовать для ввода стандартную функцию Input (), так как лучше пониматься будет. Вам бы советовал в своих программах использовать функцию GetKey () так как она не останавливает цикл.
Repeat
Mes$=Input() ; вводим своё сообщение WriteLine Stream,Mes$ ; записываем SendUDPMsg Stream,IntIP(DestIP$),Port ; отсылаем
Выше описана отправка сообщения. Как принимать сообщения вы уже знаете:
If RecvUDPMsg (Stream) Then NewMes$=ReadLine (Stream) Endif
Print NewMsg$
Until Keyhit(1)
WriteLine Stream,”User “ +_IP+” is OffLine “ SendUDPMsg Stream,IntIP(DestIP$),Port
End
Ну с программой кое как разобрались думаю.
Также скажу пару слов о таких полезных функциях как
UDPMsgPort - возвращает порт от которого пришло сообщение
UDPMsgIP – возвращает IP в том случае если сообщение пришло, и 0 если нет
UDPTimeouts - частота, т.е. с какой частотой надо проверять, пришло ли сообщение
Еще хотел бы добавить, что без сервера затруднительно писать программу, потому как необходимо подсоединятся к каждому компьютеру по отдельности. Конечно можно написать программу для небольшой сети перебирая IP адреса например от 0.0.0.1 до 0.225.255.255. Но это весьма долго, и неприемлемо. Сейчас я постараюсь объяснить как написать сервер, и приведу пример.
В чем заключается главная задача сервера? – Ответ - обслуживать клиентов ! Он принимает входящие сообщения, и отправляет их тем, кому они были предназначены. Он принимает три пакета: (в моем случае) 1 пакет - это порт, т.е. порт того, кому предназначено передаваемое сообщение 2 пакет - это IP тоже IP – адрес того, кому его надо передать 3 пакет - это само сообщение
Пример простого сервера
(здесь клиент должен отправить 2 пакет с указанным IP в ЦЕЛОЧИСЛЕННОМ виде)
Graphics 320,240,0,2 SetBuffer BackBuffer () AppTitle "ASoftware Home Server"
c=CountHostIPs ("") n$=HostIP(c) ip$=DottedIP(n$)
Print "Starting server..." Print "Please wait" Delay 1000 srv=CreateUDPStream (50345) If srv<>0 Then Print "Server is started at "+CurrentTime () Else Print "Server failed to start" Print "Press any key to continue" WaitKey() End EndIf Print "Integer IP is "+n$ Print "Dotted IP is "+ip$
Repeat If RecvUDPMsg (srv) Then ;Get Port port$=ReadLine (srv) ;Get integer IP Int_IP$=ReadLine (srv) ;Get messege msg$=ReadLine (srv)
WriteLine srv,msg$ SendUDPMsg srv,Int_IP$,port$ EndIf
Locate 0,200 Text 0,100," Server work a station by "+ip$
Delay 10 Flip Until KeyHit(1) End
Delay 10 в конце нужен для того чтобы не перегружать сервер, т.е. что бы программа нормально работала, не перегружая компьютер (это касается того случая, когда очень много клиентов отсылают свои сообщения в один промежуток времени) (порядка 150-255 клиентов в секунду). Клиенты потерпят какую-то секунду, и заодно и сервер будет нормально работать.
Ну вот и всё, удачи вам в ваших нелегких проектах!
|