我正在编写一个大学项目,包括使用POSIX套接字和C ++编写聊天客户端和服务器。
客户端应该使用P2P进行交谈,例如每个客户端都有自己的开放UDP套接字,通过该套接字发送和接收来自/向其他客户端的消息。
我的问题是双重的:
据我所知,传递INADDR_ANY应该绑定到我的本地地址,传递端口号0应该让操作系统选择一个空闲端口,我做错了什么?
这是我的UDPSocket类的构造函数:
UDPSocket::UDPSocket(int port){
socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
// clear the s_in struct
bzero((char *) &in, sizeof(in)); /* They say you must do this */
//sets the sin address
in.sin_family = (short)AF_INET;
in.sin_addr.s_addr = htonl(INADDR_ANY); /* WILDCARD */
in.sin_port = htons((u_short)port);
fsize = sizeof(from);
//bind the socket on the specified address
if(bind(socket_fd, (struct sockaddr *)&in, sizeof(in))<0){
perror ("Error naming channel");
}
}
这是初始化:
m_Socket = new UDPSocket(0);
这是我用来检索绑定地址的方法:(UDPSocket继承Socket)
std::string Socket::GetSocketAddress()
{
struct sockaddr_in addr;
int len = sizeof(addr);
getpeername(socket_fd, (struct sockaddr*)&addr, (socklen_t*)&len);
char ipAddressBuffer[50];
memset(ipAddressBuffer, 0, sizeof(ipAddressBuffer));
sprintf(ipAddressBuffer, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
return ipAddressBuffer;
}
任何帮助将不胜感激, 阿维。
答案 0 :(得分:2)
您正在使用foreach ($array as $key => $value) {}
,它会为您提供已连接套接字的远程地址。如果检查getpeername()的返回值,则应指示失败。
请注意,您的套接字绑定到特殊的0.0.0.0地址,这意味着&#34;所有本地接口&#34;,以便getockname()也将返回。
答案 1 :(得分:0)
回答更一般的问题“如何与UDP建立点对点通信”:
使用UDP套接字,虽然您可以使用connect
,但您通常不希望这样做,因为这限制了每个套接字的单个对等体。相反,您希望在每个对等体中使用单个未连接的UDP套接字与sendto
和recvfrom
系统调用一起发送和接收具有不同地址的数据包。
sendto
函数接收数据包和对等地址以发送它,而recvfrom
函数返回数据包及其来自的对等地址。使用单个套接字,无需与select
或poll
进行多路复用 - 您只需调用recvfrom
即可从任何来源获取下一个数据包。当你得到一个数据包时,你也得到了对等地址来发送数据包(返回)。
启动时,您的对等方将创建一个套接字并将其绑定到INADDR_ANY
(允许它在计算机上的任何接口或广播地址上接收数据包)以及分配给您的特定端口程序或端口0 (允许操作系统选择任何未使用的端口)。在后一种情况下,您需要使用getsockname
来获取端口并将其报告给用户。一旦设置了套接字,对等程序就可以sendto
它所知道的任何对等体,或者recvfrom
任何对等体(包括那些它还不知道的对等体)。
所以唯一棘手的部分是引导 - 让第一个数据包流动,以便对等方可以接收它们并找出它们的对等地址进行通信。一种方法是在启动每个对等体时在命令行上指定对等地址。你将开始没有参数的第一个(因为它还没有同行)。它将仅从(在套接字设置之后)重新获取以从对等体获取分组。以第一个地址作为参数开始第二个。它向第一个对等体发送一个或多个数据包,一旦获得第一个数据包,就会知道新的对等体。现在在命令行上启动第三个客户端,其中包含前两个地址...