winsock - библиотека для работы с сокетами
+2
tux
Eric-S
Участников: 6
Страница 1 из 1
библиотеки для работы с сокетами
Вопрос, какие библиотеки есть для работы с сокетами?
В папке lib нашел
mswsock.dll
wsock32.dll
Это всё только под windows?
Или есть кросплатформенные?
В папке lib нашел
mswsock.dll
wsock32.dll
Это всё только под windows?
Или есть кросплатформенные?
Последний раз редактировалось: Eric-S (Пн Сен 22, 2008 4:51 am), всего редактировалось 1 раз(а)
Re: winsock - библиотека для работы с сокетами
они под винду, но помоему все функции те же, что и линухе, при компиляции выбирается нужный заголовочный файл и компилится должно без проблем (правда сам компилить еще не пробывал)
Re: winsock - библиотека для работы с сокетами
Ага! Значит тот код, который ты мне прислал, он почти кросплатформенный!?
Меня смущала расшифровка winSocket (wsock).
Меня смущала расшифровка winSocket (wsock).
Re: winsock - библиотека для работы с сокетами
вот там какраз основное отличие - это регистрация сообщений на сокете, в каждой операционке это делается по своему, допустим в винде он привязывается к хендлу окна (чего в линухе вообще нет) и регистрируется виндовое событие, по которому происходят изменения на нем, а линухе незнаю, но функции обработки должны быть те же
пример сервера
Эту програмку прислал мне Tux, собственно именно о ней был разговор в предыдущих постах.
Здесь продемонстрирована работа с сокетами, с подробными коментариями.
Аккуратно копируем прогу, лучше из поля редактирования после нажатия "цитировать", т.к. напрямки код портиться.
Компилим, запускаем. Браузером идём на сайт
http://127.0.0.1:80
И если всё ок, то видим страничку сделанную этой прогой.
Как разбираться с фаэрволами и др запущенными серверами, которые могут вам помешать, учить не буду. Так как это отдельная тема, смотрите в мануалы или идите на спец форумы.
[code]
#include once "windows.bi"
#include once "win\winsock.bi"
const CONFIG_IP="127.0.0.1" 'IP, на котором вешаем прослушку сокета
const CONFIG_CLIENT_MAX=50 'максимальное кол-во подключений к серваку
const SERVER_READ_BUF=100000 'максимальный размер буфера отправляемых данных
const WM_SOCKET = WM_USER+100 'виндовое сообщение, которое будет сообщать о событиях на сокете
dim shared gServerMainSocket as SOCKET 'основной сокет, при работе сервака делаются его копии
dim shared gSocket as uinteger 'активный сокет
dim shared gtServerSockAddr as sockaddr_in 'структура настройки сокета
dim shared gServerWnd as HWND 'хендл окна
declare function WinMain (byval hInstance as HINSTANCE, byval hPrevInstance as HINSTANCE, byval szCmdLine as string, byval iCmdShow as integer) as integer
declare function WndProc (byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare sub sServerStart() 'запустить сервак
declare sub sServerStop() 'остановить сервак
declare sub sServerRecv(byval pSocket as uinteger, byref pStr as string) 'срабатывает, когда получены данные на сокет
declare sub sServerSend(byref pStr as string, pLenStr as integer) 'послать на сокет данные
declare sub sServerSendEnd() 'закрыть сокет, необходимо при окончании отправки данных браузерц
declare function fIPStr2Int(byval pIP as string) as uinteger 'преобразовать IP из строки в бинарный вид
function WinMain (byval hInstance as HINSTANCE, byval hPrevInstance as HINSTANCE, byval szCmdLine as string, byval iCmdShow as integer) as integer
'стандартная процедура по созданию окна, наскока я понял, сокет нельзя создать, не создав для него окно
dim wMsg as MSG
dim wcls as WNDCLASS
wcls.style=CS_HREDRAW or CS_VREDRAW
wcls.lpfnWndProc=@WndProc 'функция обработки сообщений
wcls.cbClsExtra=0
wcls.cbWndExtra=0
wcls.hInstance=hInstance
wcls.hIcon=LoadIcon(NULL, IDI_APPLICATION)
wcls.hCursor=LoadCursor(NULL, IDC_ARROW)
wcls.hbrBackground=GetStockObject(WHITE_BRUSH)
wcls.lpszMenuName=NULL
wcls.lpszClassName=@"ClassServer"
'регистрируем класс окна
if RegisterClass(@wcls)=FALSE then
print "ERROR: not RegisterClass"
sleep
end if
'создаем окно, но не загружаем его, тк нафиг оно не нужно
gServerWnd = CreateWindowEx(0, @"ClassServer", "servak", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL)
'цикл обработки сообщений винды
while GetMessage(@wMsg, NULL, 0, 0)<>FALSE
TranslateMessage @wMsg
DispatchMessage @wMsg
wend
function=wMsg.wParam
end function
function WndProc (byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
'обрабатываем сообщения
select case(wMsg)
case WM_CREATE 'создание окна
closesocket gServerMainSocket
gServerMainSocket=socket_(PF_INET, SOCK_STREAM, 0) 'открываем сокет
WSAAsyncSelect gServerMainSocket, hWnd, WM_SOCKET, FD_ACCEPT 'говорим винде, какое сообщение (WM_SOCKET) посылать при событиях на сокете
gtServerSockAddr.sin_family=AF_INET
gtServerSockAddr.sin_port=htons(80) 'используем 80-ый порт (типа стандартный для http)
gtServerSockAddr.sin_addr.S_addr=fIPStr2Int(CONFIG_IP)
print "Server running on IP=" & CONFIG_IP
bind gServerMainSocket, cast(PSOCKADDR, @gtServerSockAddr), len(gtServerSockAddr) 'привязываем сокет с настроенным адресом (если функция вернула не 0, значит занят порт)
listen gServerMainSocket, CONFIG_CLIENT_MAX 'слушаем сокет
exit function
case WM_SOCKET 'события на сокете
select case(lParam) 'типа че случилось
case FD_ACCEPT 'помоему срабатывает после Бинда
dim ks as SOCKET
ks=accept(wParam, cast(PSOCKADDR, @gtServerSockAddr), 0)
WSAAsyncSelect ks, hWnd, WM_SOCKET, FD_READ+FD_CLOSE
exit function
case FD_READ 'когда на сокет пришли данные
dim pBuf as zstring*SERVER_READ_BUF+1
recv wParam, pBuf, SERVER_READ_BUF, 0
sServerRecv wParam, pBuf 'vizov iz globalnoi funkcii
exit function
case 658898976 'закрытие сокета, поидее должен быть FD_CLOSE, но почемуто у меня выдает такое число
closesocket wParam
exit function
end select
exit function
case WM_DESTROY 'закрытие окна
PostQuitMessage 0
exit function
end select
function=DefWindowProc(hWnd, wMsg, wParam, lParam)
end function
sub sServerStart()
dim wsaDat as WSAData
dim pStart as integer
WSAStartup &H101, @wsaDat 'инициализация сокета
WinMain GetModuleHandle(null), null, "", SW_NORMAL 'вызов основной виндовой функции создания окна
end sub
sub sServerStop()
PostMessage gServerWnd, WM_CLOSE, 0, 0 'убиваем окно
end
end sub
'основная функция обработки сообщений из сокета
'pSocket - сокет, на который пришло сообщение, pStr - данные с сокета
sub sServerRecv(byval pSocket as uinteger, byref pStr as string)
dim as string pTmp
gSocket=pSocket 'запихиваем номер сокета в глобальную переменную, просто у меня много функций, которые его используют, и таскать в параметрах его запарился
print pStr 'то, что прислал браузер
'формируем http заголовок, отправляемый браузеру, долго втуплял куда его надо отправлять
'оказывается вместе с хтмл-кой
pTmp="HTTP/1.1 200 OK" & chr(13) & chr(10)
pTmp=pTmp & "Content-Type: text/html; charset=windows-1251" & chr(13) & chr(10) & chr(13) & chr(10) 'обязательно в конце заголовка нужно ставит двойной перевод строки
pTmp=pTmp & "<html><head><meta http-equiv=Content-Type content=""text/html; charset=windows-1251""><title>Заголовок"
pTmp=pTmp & "</title></head><body>"
pTmp=pTmp & "<h1>Заработало!</h1>"
pTmp=pTmp & "</body></html>"
sServerSend pTmp, len(pTmp)
sServerSendEnd
end sub
sub sServerSend(byref pStr as string, pLenStr as integer) 'pStr - отправляемые данные, pLenStr - размер данных
send gSocket, pStr, pLenStr, 0
end sub
sub sServerSendEnd()
closesocket gSocket
end sub
function fIPStr2Int(byval pIP as string) as uinteger
dim as ubyte pB1, pB2, pB3, pB4
dim i as byte, j as byte
i=instr(pIP, ".")
pB1=val(left(pIP, i-1))
i+=1
j=instr(i, pIP, ".")
pB2=val(mid(pIP, i, j-i))
j+=1
i=instr(j, pIP, ".")
pB3=val(mid(pIP, j, i-j))
i+=1
pB4=val(mid(pIP, i, 3))
function=pB1+pB2*&H100+pB3*&H10000+pB4*&H1000000
end function
sServerStart
'далее все обрабатывается через sServerRecv[
/code]
Здесь продемонстрирована работа с сокетами, с подробными коментариями.
Аккуратно копируем прогу, лучше из поля редактирования после нажатия "цитировать", т.к. напрямки код портиться.
Компилим, запускаем. Браузером идём на сайт
http://127.0.0.1:80
И если всё ок, то видим страничку сделанную этой прогой.
Как разбираться с фаэрволами и др запущенными серверами, которые могут вам помешать, учить не буду. Так как это отдельная тема, смотрите в мануалы или идите на спец форумы.
[code]
#include once "windows.bi"
#include once "win\winsock.bi"
const CONFIG_IP="127.0.0.1" 'IP, на котором вешаем прослушку сокета
const CONFIG_CLIENT_MAX=50 'максимальное кол-во подключений к серваку
const SERVER_READ_BUF=100000 'максимальный размер буфера отправляемых данных
const WM_SOCKET = WM_USER+100 'виндовое сообщение, которое будет сообщать о событиях на сокете
dim shared gServerMainSocket as SOCKET 'основной сокет, при работе сервака делаются его копии
dim shared gSocket as uinteger 'активный сокет
dim shared gtServerSockAddr as sockaddr_in 'структура настройки сокета
dim shared gServerWnd as HWND 'хендл окна
declare function WinMain (byval hInstance as HINSTANCE, byval hPrevInstance as HINSTANCE, byval szCmdLine as string, byval iCmdShow as integer) as integer
declare function WndProc (byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare sub sServerStart() 'запустить сервак
declare sub sServerStop() 'остановить сервак
declare sub sServerRecv(byval pSocket as uinteger, byref pStr as string) 'срабатывает, когда получены данные на сокет
declare sub sServerSend(byref pStr as string, pLenStr as integer) 'послать на сокет данные
declare sub sServerSendEnd() 'закрыть сокет, необходимо при окончании отправки данных браузерц
declare function fIPStr2Int(byval pIP as string) as uinteger 'преобразовать IP из строки в бинарный вид
function WinMain (byval hInstance as HINSTANCE, byval hPrevInstance as HINSTANCE, byval szCmdLine as string, byval iCmdShow as integer) as integer
'стандартная процедура по созданию окна, наскока я понял, сокет нельзя создать, не создав для него окно
dim wMsg as MSG
dim wcls as WNDCLASS
wcls.style=CS_HREDRAW or CS_VREDRAW
wcls.lpfnWndProc=@WndProc 'функция обработки сообщений
wcls.cbClsExtra=0
wcls.cbWndExtra=0
wcls.hInstance=hInstance
wcls.hIcon=LoadIcon(NULL, IDI_APPLICATION)
wcls.hCursor=LoadCursor(NULL, IDC_ARROW)
wcls.hbrBackground=GetStockObject(WHITE_BRUSH)
wcls.lpszMenuName=NULL
wcls.lpszClassName=@"ClassServer"
'регистрируем класс окна
if RegisterClass(@wcls)=FALSE then
print "ERROR: not RegisterClass"
sleep
end if
'создаем окно, но не загружаем его, тк нафиг оно не нужно
gServerWnd = CreateWindowEx(0, @"ClassServer", "servak", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL)
'цикл обработки сообщений винды
while GetMessage(@wMsg, NULL, 0, 0)<>FALSE
TranslateMessage @wMsg
DispatchMessage @wMsg
wend
function=wMsg.wParam
end function
function WndProc (byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
'обрабатываем сообщения
select case(wMsg)
case WM_CREATE 'создание окна
closesocket gServerMainSocket
gServerMainSocket=socket_(PF_INET, SOCK_STREAM, 0) 'открываем сокет
WSAAsyncSelect gServerMainSocket, hWnd, WM_SOCKET, FD_ACCEPT 'говорим винде, какое сообщение (WM_SOCKET) посылать при событиях на сокете
gtServerSockAddr.sin_family=AF_INET
gtServerSockAddr.sin_port=htons(80) 'используем 80-ый порт (типа стандартный для http)
gtServerSockAddr.sin_addr.S_addr=fIPStr2Int(CONFIG_IP)
print "Server running on IP=" & CONFIG_IP
bind gServerMainSocket, cast(PSOCKADDR, @gtServerSockAddr), len(gtServerSockAddr) 'привязываем сокет с настроенным адресом (если функция вернула не 0, значит занят порт)
listen gServerMainSocket, CONFIG_CLIENT_MAX 'слушаем сокет
exit function
case WM_SOCKET 'события на сокете
select case(lParam) 'типа че случилось
case FD_ACCEPT 'помоему срабатывает после Бинда
dim ks as SOCKET
ks=accept(wParam, cast(PSOCKADDR, @gtServerSockAddr), 0)
WSAAsyncSelect ks, hWnd, WM_SOCKET, FD_READ+FD_CLOSE
exit function
case FD_READ 'когда на сокет пришли данные
dim pBuf as zstring*SERVER_READ_BUF+1
recv wParam, pBuf, SERVER_READ_BUF, 0
sServerRecv wParam, pBuf 'vizov iz globalnoi funkcii
exit function
case 658898976 'закрытие сокета, поидее должен быть FD_CLOSE, но почемуто у меня выдает такое число
closesocket wParam
exit function
end select
exit function
case WM_DESTROY 'закрытие окна
PostQuitMessage 0
exit function
end select
function=DefWindowProc(hWnd, wMsg, wParam, lParam)
end function
sub sServerStart()
dim wsaDat as WSAData
dim pStart as integer
WSAStartup &H101, @wsaDat 'инициализация сокета
WinMain GetModuleHandle(null), null, "", SW_NORMAL 'вызов основной виндовой функции создания окна
end sub
sub sServerStop()
PostMessage gServerWnd, WM_CLOSE, 0, 0 'убиваем окно
end
end sub
'основная функция обработки сообщений из сокета
'pSocket - сокет, на который пришло сообщение, pStr - данные с сокета
sub sServerRecv(byval pSocket as uinteger, byref pStr as string)
dim as string pTmp
gSocket=pSocket 'запихиваем номер сокета в глобальную переменную, просто у меня много функций, которые его используют, и таскать в параметрах его запарился
print pStr 'то, что прислал браузер
'формируем http заголовок, отправляемый браузеру, долго втуплял куда его надо отправлять
'оказывается вместе с хтмл-кой
pTmp="HTTP/1.1 200 OK" & chr(13) & chr(10)
pTmp=pTmp & "Content-Type: text/html; charset=windows-1251" & chr(13) & chr(10) & chr(13) & chr(10) 'обязательно в конце заголовка нужно ставит двойной перевод строки
pTmp=pTmp & "<html><head><meta http-equiv=Content-Type content=""text/html; charset=windows-1251""><title>Заголовок"
pTmp=pTmp & "</title></head><body>"
pTmp=pTmp & "<h1>Заработало!</h1>"
pTmp=pTmp & "</body></html>"
sServerSend pTmp, len(pTmp)
sServerSendEnd
end sub
sub sServerSend(byref pStr as string, pLenStr as integer) 'pStr - отправляемые данные, pLenStr - размер данных
send gSocket, pStr, pLenStr, 0
end sub
sub sServerSendEnd()
closesocket gSocket
end sub
function fIPStr2Int(byval pIP as string) as uinteger
dim as ubyte pB1, pB2, pB3, pB4
dim i as byte, j as byte
i=instr(pIP, ".")
pB1=val(left(pIP, i-1))
i+=1
j=instr(i, pIP, ".")
pB2=val(mid(pIP, i, j-i))
j+=1
i=instr(j, pIP, ".")
pB3=val(mid(pIP, j, i-j))
i+=1
pB4=val(mid(pIP, i, 3))
function=pB1+pB2*&H100+pB3*&H10000+pB4*&H1000000
end function
sServerStart
'далее все обрабатывается через sServerRecv[
/code]
Re: winsock - библиотека для работы с сокетами
А где можно вобще почитать про winsock? Просто хотелось бы реализовать отправку на email, но ума не приложу как это сделать...
Re: winsock - библиотека для работы с сокетами
если отправка e-mail то это можно и проще организовать.
Например есть консольная утилитка sendmail она отправляет сообщения прямо из командной строки.
Есть win api или точнее mail api. Но я про них только слышал, точнее не знаю.
А ещё в сети есть несколько статеек, типа отправка почты...
Они правда про php, но ведь нужны сокеты, а там именно они и показаны.
Ну и протоколы в крации описаны.
Например есть консольная утилитка sendmail она отправляет сообщения прямо из командной строки.
Есть win api или точнее mail api. Но я про них только слышал, точнее не знаю.
А ещё в сети есть несколько статеек, типа отправка почты...
Они правда про php, но ведь нужны сокеты, а там именно они и показаны.
Ну и протоколы в крации описаны.
UDP socket
Здесь TCP сокет. С UDP, по идее, должно быть проще, но что то у меня нифига не выходит...Eric-S пишет:Эту програмку прислал мне Tux, собственно именно о ней был разговор в предыдущих постах.
Здесь продемонстрирована работа с сокетами
Имею железку-клиента, который посылает на сервер ASCII строки через UDP. Собственно, надо написать сервер... На VB6 через Winsock получалось на раз. А вот на FB что-то совсем запутался...
Заранее объявил необходимые переменные:
- Код:
Const WM_SOCKET = WM_USER + 100
Dim Shared wndMain As HWND
Dim Shared sendBuf As String
Dim Shared recvBuf As ZString * SERVER_READ_BUF + 1
Dim Shared wsaData As WSADATA
Dim Shared udpSocket As socket
Dim Shared udpSockAddr As sockaddr_in
- Код:
Case WM_CREATE
' create UDP socket
If WSAStartup (MAKEWORD (1, 1), @wsaData) <> 0 Then
Print "Error: WSA Startup filed"
Sleep
End
End If
udpSocket = opensocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
If udpSocket = 0 Then
Print "Error: "; WSAGetLastError; "Calling: socket ()"
Sleep
End
End If
WSAAsyncSelect udpSocket, wndMain, WM_SOCKET, FD_ACCEPT
With udpSockAddr
.sin_family = AF_INET
.sin_port = htons (9001)
End With
If bind (udpSocket, Cast (PSOCKADDR, @udpSockAddr), Len (udpSockAddr)) < 0 Then
Print "Error bind"
Sleep
End
End If
Case WM_SOCKET
Select Case l_param
Case FD_READ
recv w_param, recvBuf, SERVER_READ_BUF, 0 ' получаем строку
Print recvBuf ' печатаем её на консоли
sendBuf = Left (recvBuf, 2) ' это уже особенность железки - она ждёт первые два байта посланной на сервер строки (packetID) в качестве подтверждения приёма строки
send udpSocket, sendBuf, 2, 0 ' отправляем подтверждение железке-клиенту
Case FD_CLOSE
closesocket w_param
End Select
Компилю как WindowsConsole. По замыслу в консольном окне должны печататься сообщения об ошибках или поступающие строки если всё работает. Но не печатается ничего... а железка говорит NO LINK
justar- Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 49
Откуда : Кишинёв, Республика Молдоа
Re: winsock - библиотека для работы с сокетами
justar!
Я в этом деле мало что смыслю. ЭТОТ пример смотрел?
Я в этом деле мало что смыслю. ЭТОТ пример смотрел?
trew- Сообщения : 331
Дата регистрации : 2010-10-14
UDP socket
Перелопатил море литературы по сокетам Беркли вообще и по winsock в частности и вроде разобрался с сабжем
Сервер
Впрочем, можно использовать и recv () - для этого надо создать связанный UDP сокет, используя на клиенте connect () вместо bind (). Это работает, хотя и противоречит теории UDP сокетов По крайней мере - при одном клиенте... Если клиентов может быть много, то не стоит так делать потому, что на UDP сервере winsock не позволяет использовать listen () и accept () и создать отдельную связь с каждым клиентом невозможно, а потому весьма вероятна путаница с заполнением структуры sockaddr_in, которая способна привести к непредсказуемым глюкам.
Если GUI делается с помощью библиотеки Window9, то опрос сокетов правильнее всего работает если расположен в основном цикле после опроса событий окна:
В общем случае это не так. Сокеты ни коим образом не связаны с GUI. Привязывать (WSAASyncSelect) сокет к сообщению WM_SOCKET и вызывать функции Беркли в нём нужно только в том случае, если окно уже есть для других целей. Ну а если GUI не нужен - можно работать с сокетами в чистой консоли или вообще в виде демона. Вот примеры консольных UDP сервера и клиента - никаких окон там нет и в помине, однако датаграммы прекрасно отправляются и принимаются.сокет нельзя создать, не создав для него окно
Сервер
- Код:
#Include "windows.bi"
#Include "win/winsock.bi"
' инициализируем библиотеку winsock
Dim wsaData As WSADATA
If WSAStartup (MAKEWORD (2, 0), @wsaData) = SOCKET_ERROR Then
Print "Winsok init error "; WSAGetLastError ()
Sleep
End
End If
' создаём UDP сокет с дескриптором sd
Dim Shared sd As socket
sd = opensocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)
If sd = INVALID_SOCKET Then
Print "Socket open error "; WSAGetLastError ()
WSACleanup ()
Sleep
End
End If
' привязываем сокет к локальному адресу и порту
Dim Shared sa As sockaddr_in
With sa
.sin_family = AF_INET
.sin_port = htons (9001) ' порт, который будем слушать
.sin_addr.s_addr = INADDR_ANY ' если у сервера один сетевой интерфейс, локальный адрес не важен
' иначе указать ip нужного интерфейса через функцию inet_addr ()
End With
If bind (sd, @sa, SizeOf (sa)) = SOCKET_ERROR Then
Print "Bind error "; WSAGetLastError ()
closesocket (sd)
WSACleanup ()
Sleep
End
End If
Dim recvBuff As ZString * 64 ' буфер для приёма датаграмм (после звёздочки указываем макс. размер буфера)
Dim numrecv As Integer ' в эту переменную recv () поместит реальную длину полученной датаграммы
' всё готово для приёма дейтаграмм
' далее крутим обычные циклы - ждём и обрабатываем полученную информацию
Do
Do
numrecv = recv (sd, @recvBuff, SizeOf (recvBuff), 0) ' опрашиваем сокет
recvBuff[numrecv] = 0 ' дописываем в буфер завершающий строку нулевой байт
Loop Until Len (recvBuff) > 1 ' крутим цикл до тех пор, пока в строке не только завершающий нуль
' т.е. ожидаем прихода датаграммы
' (почему то Loop Until numrecv > 0 у меня не заработало,
' хотя по теории так правильнее)
Print recvBuff
Loop Until numrecv = -1 ' продолжаем принимать датаграммы, пока recv () не сообщит об ошибке сокета
' завершающие штрихи
closesocket (sd) ' хотя по идее оператор End закрывает всё, что можно ;) теория рекомендует закрывать сокет
WSACleanup ' и библиотеку явным образом.
End
- Код:
#Include "windows.bi"
#Include "win/winsock.bi"
' начинаем аналогично серверу
Dim wsaData As WSADATA
If WSAStartup (MAKEWORD (2, 0), @wsaData) = SOCKET_ERROR Then
Print "Winsok init error "; WSAGetLastError ()
Sleep
End
End If
Dim sd As socket
sd = opensocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)
If sd = INVALID_SOCKET Then
Print "Socket open error "; WSAGetLastError ()
WSACleanup ()
Sleep
End
End If
Dim sa As sockaddr_in
With sa
.sin_family = AF_INET
.sin_port = 0 ' первое отличие - локальный порт клиента не важен, winsock сама выберет подходящий свободный
' ВНИМАНИЕ! если указать здесь порт сервера, после bind () получите ошибку 10048 "порт занят"
.sin_addr.s_addr = INADDR_ANY
End With
If bind (sd, @sa, SizeOf (sa)) = SOCKET_ERROR Then
Print "Bind error "; WSAGetLastError ()
closesocket (sd)
WSACleanup ()
Sleep
End
End If
Print "Socket "; sd; " listened OK"
Randomize Timer
Dim servaddr As sockaddr_in ' второе отличие от сервера - добавляется структура параметров сервера
Dim sendBuff As ZString * 64
Dim i As Integer
With servaddr
.sin_family = AF_INET
.sin_port = htons (9001) ' а вот тут уже указываем порт, который слушает сервер
.sin_addr.s_addr = inet_addr ("127.0.0.1") ' это IP сервера
End With
Do
'генерим случайную строку длиной до 64 байт (так как макс. размер буфера выбран 64)
For i = 0 To Int (Rnd (1) * 63 -1)
sendBuff[i] = Cast (UByte, Int (Rnd (1) * 253 + 1))
Next
sendBuff[i+1]=0
' отправляем датаграмму на сервер
' в отличии от send (), отправляющей на адрес из настроек собственного сокета,
' sendto () имеет два дополнительных параметра, описывающих сокет сервера.
' так как UDP протокол без установки связи, по другому клиент работать не сможет
If sendto (sd, @sendBuff, SizeOf (sendBuff), 0, @servaddr, SizeOf (servaddr)) = SOCKET_ERROR Then
Print "Send error "; WSAGetLastError ()
Else
Print "Sending "; sendBuff
End If
Sleep Int (Rnd (1) * 5000)
Loop ' повторяем отправки датаграмм пока не надоест ;)
Впрочем, можно использовать и recv () - для этого надо создать связанный UDP сокет, используя на клиенте connect () вместо bind (). Это работает, хотя и противоречит теории UDP сокетов По крайней мере - при одном клиенте... Если клиентов может быть много, то не стоит так делать потому, что на UDP сервере winsock не позволяет использовать listen () и accept () и создать отдельную связь с каждым клиентом невозможно, а потому весьма вероятна путаница с заполнением структуры sockaddr_in, которая способна привести к непредсказуемым глюкам.
Если GUI делается с помощью библиотеки Window9, то опрос сокетов правильнее всего работает если расположен в основном цикле после опроса событий окна:
- Код:
Do
event = WindowEvent
Select Case event
Case EventClose
End
End Select
' здесь работаем с сокетами
Loop
justar- Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 49
Откуда : Кишинёв, Республика Молдоа
Re: winsock - библиотека для работы с сокетами
justar пишет:
Причём надо использовать именно WindowEvent - c WaitEvent у меня почему то (почему именно пока не понял) глючит... Так же не у меня не получился и вариант с привязкой сообщения WM_SOCKET к хэндлу окна, созданного библиотекой Window9, с последующим перенаправлением сообщений Windows на свой обработчик (SetWindowCallback).
Выложи код, в котором у тебя не получается работа с window9. Может что подскажу
trew- Сообщения : 331
Дата регистрации : 2010-10-14
Re: winsock - библиотека для работы с сокетами
Спасибо, но уже не актуально так как нашёл вариант работающего кода (разместив опрос сокетов в основном цикле после опроса евентов windows9. Да так и проще получаетсяtrew пишет:Может что подскажу
justar- Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 49
Откуда : Кишинёв, Республика Молдоа
Re: winsock - библиотека для работы с сокетами
тоже решил немного заморочиться с сокетами. вот четыре статейки, только код на c. написано доступно и понятно. жаль, что больше не выпускает он эти статьи.
Winsock для всех (часть 1)
Winsock для всех (часть 2)
Winsock для всех (часть 3)
Winsock для всех (часть 4)
внимательно смотрим, вродь опечатки в коде есть, zeromemory - zeormemory
Winsock для всех (часть 1)
Winsock для всех (часть 2)
Winsock для всех (часть 3)
Winsock для всех (часть 4)
внимательно смотрим, вродь опечатки в коде есть, zeromemory - zeormemory
electrik- Сообщения : 391
Дата регистрации : 2008-09-02
Возраст : 43
Откуда : галактика Млечный путь, система Солнечная, планета Земля, страна россия, город Санкт Петербург
Re: winsock - библиотека для работы с сокетами
electrik пишет:тоже решил немного заморочиться с сокетами. вот четыре статейки, только код на c. написано доступно и понятно. жаль, что больше не выпускает он эти статьи.
Winsock для всех (часть 1)
Winsock для всех (часть 2)
Winsock для всех (часть 3)
Winsock для всех (часть 4)
внимательно смотрим, вродь опечатки в коде есть, zeromemory - zeormemory
Хороший сайт, почитаю, спасибо за наводку.
trew- Сообщения : 331
Дата регистрации : 2010-10-14
Страница 1 из 1
Права доступа к этому форуму:
Вы не можете отвечать на сообщения
|
|