Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
adonin
Зарегистрирован: 11.10.2005 Сообщения: 35
|
Добавлено: Ср Ноя 23 2005 16:29 Заголовок сообщения: understanding windows sockets |
|
|
Сервер принимает 3 соединения от клиентов (соединение по TCP):
Код: |
listen(s,3);
for(i=0;i<3;i++)
{
scl[i]=accept(s,(sockaddr*)&sacl[i],NULL);
send(scl[i],str,k,0);
}
|
Получается, что у сервера 3 сокета на одном порту? Или нет?
Каким образом поддерживается несколько соединений TCP через один порт? Используются свободные порты?
ИМХО сокет однозначно определяется IP и номером порта, или нет? Объясните!
ЗЫ. Пробовал на клиентах получить адреса сервера через recvfrom, но там структура заполняется нулями:
Код: |
for(i=0;i<3;i++)
{
s[i]=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
bind(s[i],(sockaddr*)&sa,sizeof(sa));
connect(s[i],(sockaddr*)&saconn,sizeof(saconn));
recvfrom(s[i],buf,600,0,(sockaddr*)&sfrom[i],&k); // в sfrom нули :(
sa.sin_port++;
}
|
|
|
Вернуться к началу |
|
|
PolAR
Зарегистрирован: 01.11.2004 Сообщения: 133
|
Добавлено: Ср Ноя 23 2005 21:45 Заголовок сообщения: |
|
|
Сокет - это действительно пара IP:port.
А соединение однозначно определяется парой сокетов : IP_cli:port_cli - IP_srv:port_srv.
Поэтому када цепляется очередной клиент, сервер порождает поток ( или процесс ) для работы с данным конкретным клиентом. Этот поток ( процесс ) обслуживает уже конкретное установленное соединение IP_cli:port_cli-IP_srv:port_srv. И все пакеты с таким набором адресов и портов идут к данному подпроцессу сервера.
А основной процесс остается в режиме прослушивания. _________________ Come Together!! Right Now.... |
|
Вернуться к началу |
|
|
adonin
Зарегистрирован: 11.10.2005 Сообщения: 35
|
Добавлено: Чт Ноя 24 2005 09:38 Заголовок сообщения: |
|
|
Спасибо! Может ещё знаешь почему recvfrom() не возвращает адрес отправителя? Раньще делал - всё работало (правда для UDP).
Цитата: | recvfrom(s[i],buf,600,0,(sockaddr*)&sfrom[i],&k); // в sfrom нули
|
|
|
Вернуться к началу |
|
|
PolAR
Зарегистрирован: 01.11.2004 Сообщения: 133
|
Добавлено: Чт Ноя 24 2005 15:39 Заголовок сообщения: |
|
|
По-моему косяк у тебя здесь:
Код: | for(i=0;i<3;i++)
{
s[i]=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
bind(s[i],(sockaddr*)&sa,sizeof(sa));
connect(s[i],(sockaddr*)&saconn,sizeof(saconn));
recvfrom(s[i],buf,600,0,(sockaddr*)&sfrom[i],&k); // в sfrom нули :(
sa.sin_port++;
} |
Конкретно в строчке:
Код: | bind(s[i],(sockaddr*)&sa,sizeof(sa)); |
Системный вызов bind выполняется для сервера и связывает его сокет с портом для последующего прослушивания
Клиенту достаточно:
Код: | s[i]=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(s[i],(sockaddr*)&saconn,sizeof(saconn)); |
Где saconn - структура, соответствующая сокету сервера, к которому цепляемся!
Я не утверждаю, потому что подзабыл уже ( 2 года назад вскольз программировал )
Когда разберешься - запости! _________________ Come Together!! Right Now.... |
|
Вернуться к началу |
|
|
adonin
Зарегистрирован: 11.10.2005 Сообщения: 35
|
Добавлено: Чт Ноя 24 2005 17:30 Заголовок сообщения: |
|
|
Спасибо за помощь, я уже разобрался. Просто recvfrom() не возвращает адрес для сокетов TCP. Она сработает для сокетов, для которых не устанавливалось соединение TCP. (UDP, Raw Sockets).
А насчет bind() ты не прав. bind() привязывает сокет к порту на локальной машине. После bind() ни один процесс в системе не может использовать этот порт. Значение порта, указанного в bind() подставляется в поле Local Port заголовка IP пакета. |
|
Вернуться к началу |
|
|
PolAR
Зарегистрирован: 01.11.2004 Сообщения: 133
|
Добавлено: Пт Ноя 25 2005 07:09 Заголовок сообщения: |
|
|
Цитата: |
А насчет bind() ты не прав. bind() привязывает сокет к порту на локальной машине. После bind() ни один процесс в системе не может использовать этот порт. Значение порта, указанного в bind() подставляется в поле Local Port заголовка IP пакета.
|
Как я понимаю эта возможность нужна искл. для серверов, а клиент берет первый попавшийся свободный порт > 1024 ( а откуда ты знаешь какой сейчас свободен??? => ты не можешь заранее сформировать sockaddr, который передается в bind!!).
А вот connect знает какие порты щас свободны, его займет и вернет тебе sockaddr в структуру, адрес на которую ты передаешь в connect вторым параметром - saconn _________________ Come Together!! Right Now.... |
|
Вернуться к началу |
|
|
adonin
Зарегистрирован: 11.10.2005 Сообщения: 35
|
Добавлено: Пт Ноя 25 2005 11:00 Заголовок сообщения: |
|
|
см. MSDN:
Цитата: |
Remarks
The bind function is used on an unconnected socket before subsequent calls to the connect or listen functions. It is used to bind to either connection-oriented (stream) or connectionless (datagram) sockets. When a socket is created with a call to the socket function, it exists in a name space (address family), but it has no name assigned to it. Use bind to establish the local association of the socket by assigning a local name to an unnamed socket.
|
Итак, перед connect() тоже надо делать dind().
А насчёт узнать какие порты свободны - существует список распространённых программ, в котором указаны используемые ими порты. Просто не использовать в своих приложениях эти порты. При этом после bind() делаем WSAGetLastError(), если !=0 делаем инкремент номера порта и повторяем bind().
З.Ы. второй параметр в connect() - адрес удаленного хоста (куда конектиться), и является входным. См. MSDN:
Цитата: |
name
[in] The name of the socket to connect to.
|
|
|
Вернуться к началу |
|
|
PolAR
Зарегистрирован: 01.11.2004 Сообщения: 133
|
Добавлено: Сб Ноя 26 2005 10:06 Заголовок сообщения: |
|
|
Я В Линухе программировал это и в клиентах bind не использовал - но все работало.
А насчет connect-a я ла#анулся.
Хорошо что у тебя все поперло! Удачи _________________ Come Together!! Right Now.... |
|
Вернуться к началу |
|
|
|