2015-03-08 57 views
0

所以我最近决定尝试使用我发现并搜索网络的指南来进行winsock和网络编程,但是我遇到了一个问题,我不确定我应该如何解决。Winsock绑定在同一个端口

我试图做一个非常简单的聊天系统,我有一个工作服务器程序和客户端程序,如果我只在客户端使用(发送消息回到同一客户端)它似乎完美工作精细。当我尝试让多个客户端连接时出现问题。我从WSAgetlasterror得到错误10048,它似乎是源的绑定函数,更具体地说,我试图在同一个端口上绑定两次(每个客户端一次)。从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只创建一个单一的被动式监听套接字并将其绑定到你的端口。客户端都连接到相同的端口,然后您在该单个被动套接字上接受这些新连接。您无需为每个客户端打开一个被动套接字。 – 2015-03-08 19:11:20

回答

-1

您必须在服务器中有1个线程专门接受新的连接。

该进程监听新连接并为该连接分配一个新端口(在服务器中),使默认端口可用于新连接。

在服务器中,当N是服务器拥有的客户端数量时,您将有N + 1套接字端口随时打开,1是侦听新连接的套接字。

看看这个: http://www.codeproject.com/Articles/7785/Single-Server-With-Multiple-Clients-a-Simple-C-Imp

+0

好吧我想我明白你的意思,我似乎设法解决这个问题,我只是做了另一个函数来处理接受,并从listentoport函数中删除原来的接受,所以现在我只在端口上使用侦听一开始,只是一个问题。如果我正确理解事情,listen的第二个参数是我可以在我使用的套接字上进行连接的连接数量,但是似乎最多只能在五个连接上?我在这里错过了什么,或者如果他们想要超过五个连接,那么会怎么做? – Gamewolf3000 2015-03-08 19:57:59

+0

我不确定具体的实现。但是我认为那些队列中的挂起连接,每次你接受一个客户端连接,你就释放一个点。所以尽管有监听器端口限制,你仍然可以有多个连接。 – eritiro 2015-03-08 20:16:11

+0

它不分配一个新的端口。接受的套接字使用与侦听套接字相同的端口。 – EJP 2016-01-19 00:42:32