2015-03-08 3 views
0

Так что я недавно решил немного поработать в winsock и сетевом программировании, используя руководство, которое я нашел и искал в сети, но у меня возникла проблема, которую я не совсем уверен, как я должен решить ,Перехват Winsock на том же порту

Я пытаюсь создать очень простую систему чата, у меня есть рабочая программа сервера и клиентская программа, и если я использую только клиент (отправка сообщения обратно одному клиенту) Кажется, что он отлично работает хорошо. Проблема возникает, когда я пытаюсь подключить несколько клиентов. Я получаю сообщение об ошибке 10048 из WSAgetlasterror и, похоже, это функция связывания, которая является источником, а более конкретно тот факт, что я пытаюсь связать на одном и том же порту дважды (один раз для каждого клиента). Оглядываясь на msdn и форумы, кажется, что можно обойти эту проблему, используя setsockopt, но я не совсем уверен, какие изменения я должен внести, а также если это самое умное решение.

Я имею в виду, что я хочу, чтобы клиенты подключались к одному порту, не так ли? Как еще клиентская программа знает, к чему подключиться? Или я просто что-то пропустил? Как я уже сказал, у меня нет предыдущего опыта работы с winsock или любым другим сетевым программированием, поэтому я мог бы делать что-то глупо.

int listenOnPort(int portno, SOCKET& reciever, SOCKET s){ 
int error = WSAStartup(0x0202, &w); 

if (error) 
{ 
    cout << "Error starting WSA"; 
    return false; //for some reason we couldn't start Winsock 
} 

if (w.wVersion != 0x0202) //Wrong Winsock version? 
{ 
    cout << "Wrong Winsock version"; 
    WSACleanup(); 
    return false; 
} 

SOCKADDR_IN addr; // The address structure for a TCP socket 

addr.sin_family = AF_INET; // Address family 
addr.sin_port = htons(portno); // Assign port no to this socket 

//Accept a connection from any IP using INADDR_ANY 
//You could pass inet_addr("0.0.0.0") instead to accomplish the 
//same thing. If you want only to watch for a connection from a 
//specific IP, specify that //instead. 
addr.sin_addr.s_addr = htonl(INADDR_ANY); 

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create a socket 

if (s == INVALID_SOCKET) 
{ 
    cout << "Couldn't create the socket"; 
    return false; //Don't continue if we couldn't create a //socket!! 
} 

if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) 
{ 
    //We couldn't bind (this will happen if you try to bind to the same 
    //socket more than once) 
    cout << "Error binding the socket"; 
    return false; 
} 

//Now we can start listening (allowing as many connections as possible to 
//be made at the same time using SOMAXCONN). You could specify any 
//integer value equal to or lesser than SOMAXCONN instead for custom 
//purposes). The function will not //return until a connection request is 
//made 
listen(s, 1); 

reciever = accept(s, NULL, NULL); 
cout << "connection established\n\n"; 

//Don't forget to clean up with CloseConnection()!} 



int main(){ 
e = WSAGetLastError(); 
listenOnPort(1337, r1, s1); 
cout << "First Client connected\n\n"; 
e = WSAGetLastError(); 

listenOnPort(1338, r2, s2); 
cout << "Second Client connected\n\n"; 
e = WSAGetLastError(); 

std::thread com1(communicate, r1, r2); 
std::thread com2(communicate, r2, r1); 

com1.join(); 
com2.join(); 

//system("pause"); 

closeConnection();} 
+1

Для TCP вы создать только один единственный пассивный сокет и привязать его к порту. Все клиенты подключаются к одному и тому же порту, а затем вы принимаете эти новые соединения в этом одиночном пассивном сокете. Вам не нужно открывать один пассивный сокет для каждого клиента. –

ответ

-1

Вы должны иметь 1 поток на сервере, предназначенный для приема новых соединений.

Процесс прослушивает новые подключения и назначает новый порт (на сервере) для этого соединения, делая порт по умолчанию доступным для новых подключений.

На сервере у вас будут порты гнезд N + 1, открытые в любое время, когда N - количество клиентов, на которых установлено сервер, а 1 - сокет, прослушивающий новые подключения.

Взгляните на это: http://www.codeproject.com/Articles/7785/Single-Server-With-Multiple-Clients-a-Simple-C-Imp

+0

Хорошо, я думаю, я понимаю, как вы имеете в виду, и мне, похоже, удалось решить проблему, я просто сделал еще одну функцию, которая обрабатывает прием и удаление оригинала accept из функции listentoport, поэтому теперь я использую только прослушивание на порту один раз в начало, только вопрос tho. Если я правильно понимаю, второй параметр прослушивания - это количество подключений, которые я могу использовать для сокета, который я использую для прослушивания, но это кажется максимальным в пять раз? Я что-то упустил здесь или как это сделать, если они хотят более пяти соединений? – Gamewolf3000

+0

Я не уверен в конкретной реализации. Но я думаю, что это ожидающие подключения в очереди, каждый раз, когда вы принимаете клиентское соединение, вы выпускаете одно место. Таким образом, вы можете иметь несколько соединений, несмотря на ограничение порта прослушивателя. – eritiro

+0

Не назначает новый порт. Принимаемый сокет использует тот же порт, что и гнездо для прослушивания. – EJP

Смежные вопросы