Recv()从DNS查询返回0(C)

Recv()从DNS查询返回0(C),c,networking,dns,C,Networking,Dns,所以我在C中创建了一个DNS代理。我使用DIG作为客户端程序;它向我的服务器发送一个查询包,我的服务器将其转发到DNS,我的服务器接收到答案,然后将它们发送回客户端 我的服务器绑定到UDP套接字;我正在通过TCP传输DNS数据包。但是,我的recv()调用(从TCP套接字)总是返回0。我将返回原始查询,但没有答案 代码: 缓冲区是300字节。除了不检查任何系统调用的错误外,一个大问题是使用。将告诉您它在缓冲区中放置了多少字节(或-1表示错误)。其中一些字节可能有零值,因此在这种情况下,strle

所以我在C中创建了一个DNS代理。我使用DIG作为客户端程序;它向我的服务器发送一个查询包,我的服务器将其转发到DNS,我的服务器接收到答案,然后将它们发送回客户端

我的服务器绑定到UDP套接字;我正在通过TCP传输DNS数据包。但是,我的recv()调用(从TCP套接字)总是返回0。我将返回原始查询,但没有答案

代码:


缓冲区是300字节。

除了不检查任何系统调用的错误外,一个大问题是使用。将告诉您它在缓冲区中放置了多少字节(或
-1
表示错误)。其中一些字节可能有零值,因此在这种情况下,
strlen(2)
根本不适用。解决这个问题,看看是否有帮助。否则,您必须解释为什么通过TCP转发并在每个数据包上连接。

除了不检查任何系统调用的错误之外,一个大问题是使用。将告诉您它在缓冲区中放置了多少字节(或
-1
表示错误)。其中一些字节可能有零值,因此在这种情况下,
strlen(2)
根本不适用。解决这个问题,看看是否有帮助。否则,您必须解释为什么通过TCP转发并在每个数据包上连接。

您当前的问题是您使用的协议不正确。DNS/TCP/IP协议与DNS/UDP/IP协议不同。阅读描述协议的RFC并遵循它们


更基本的问题是给定代码的设计问题。在前端只有UDP/IP的情况下,在后端为每个查询TCP/IP建立一个连接是没有意义的,尤其是在网络开销方面。此外:正确编写的应用程序必须处理大型UDP/IP数据包、被截断的响应、被截断或格式不正确的查询、TCP/IP连接超时和重置、循环检测以及DNS/UDP/IP重试。但这超出了问题的范围。

你眼前的问题是你讲的协议不正确。DNS/TCP/IP协议与DNS/UDP/IP协议不同。阅读描述协议的RFC并遵循它们


更基本的问题是给定代码的设计问题。在前端只有UDP/IP的情况下,在后端为每个查询TCP/IP建立一个连接是没有意义的,尤其是在网络开销方面。此外:正确编写的应用程序必须处理大型UDP/IP数据包、被截断的响应、被截断或格式不正确的查询、TCP/IP连接超时和重置、循环检测以及DNS/UDP/IP重试。但这超出了问题的范围。

recv()在另一端断开连接时返回零。因此,您正在使另一端断开连接,而不是发送任何数据。可能它不理解您发送的内容。

recv()在另一端断开连接时返回零。因此,您正在使另一端断开连接,而不是发送任何数据。它可能不理解您发送的内容。

连接()和发送()的返回值是什么?它们是您期望的吗?
connect()
send()
的返回值是多少?它们是你想要的吗?我把strlen改成了sizeof();我仍然没有收到服务器的响应。我检查了所有系统调用是否有错误——recvfrom和sendto返回300,connect()返回0,send返回正确的字节数。(也是300)我已经转储了数据包,没有格式问题。似乎这一切都取决于recv()调用。请使用返回值
recvfrom()
而不是
sizeof
。然后,当TCP
recv()
返回零时,表示另一端断开连接。请参阅@JdeBP answer-您没有发送正确的请求,因此服务器只是关闭您的连接;我仍然没有收到服务器的响应。我检查了所有系统调用是否有错误——recvfrom和sendto返回300,connect()返回0,send返回正确的字节数。(也是300)我已经转储了数据包,没有格式问题。似乎这一切都取决于recv()调用。请使用返回值
recvfrom()
而不是
sizeof
。然后,当TCP
recv()
返回零时,表示另一端断开连接。请参阅@JdeBP answer-您没有发送正确的请求,因此服务器只是关闭您的连接。有关如何不编写DNS代理,请参阅RFC 5625。我计划稍后解决连接详细信息;我只是想先从DNS服务器获得正确的响应。我现在看到了区别。。。如何发送2字节长度的字段?谢谢;我发现了这一点。关于如何不编写DNS代理,请参阅RFC 5625。我计划稍后解决连接详细信息;我只是想先从DNS服务器获得正确的响应。我现在看到了区别。。。如何发送2字节长度的字段?谢谢;我明白了。我现在真的收到了答案;我通过发送/接收一个2字节长的字段作为数据包传输的前缀。。。但我不会收回授权/附加记录部分。。。快到了!我现在真的收到了答案;我通过发送/接收一个2字节长的字段作为数据包传输的前缀。。。但我不会收回授权/附加记录部分。。。快到了!
fromlen=sizeof(client);
recvfrom(UDPSock,buffer,sizeof(buffer),0,(struct sockaddr *)&client,&fromlen); //receive from client
int msglen=strlen(buffer);
connect(TCPSock,(struct sockaddr*) &dest, sizeof(dest)); //connect to DNS
int m=send(TCPSock,buffer,msglen,0); //send packet to dns
recv(TCPSock,buffer,sizeof(buffer),0); //this returns 0

//send back
sendto(UDPSock,buffer,sizeof(buffer),0,(struct sockaddr *)&client,fromlen); //send message back`