如何在 C++ 中创建 RAW TCP/IP 数据包?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/78184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I create RAW TCP/IP packets in C++?
提问by
I'm a beginning C++ programmer / network admin, but I figure I can learn how to do this if someone points me in the right direction. Most of the tutorials are demonstrated using old code that no longer works for some reason.
我是 C++ 初学者/网络管理员,但我想如果有人指出我正确的方向,我可以学习如何做到这一点。大多数教程都是使用由于某种原因不再起作用的旧代码进行演示的。
Since I'm on Linux, all I need is an explanation on how to write raw Berkeley sockets. Can someone give me a quick run down?
因为我在 Linux 上,所以我只需要解释一下如何编写原始的 Berkeley 套接字。有人可以给我快速运行吗?
回答by X-Istence
Start by reading Beej's guide on socket programming. It will bring you up to speed on how to start writing network code. After that you should be able to pick up more and more information from reading the man pages.
首先阅读Beej 的套接字编程指南。它将带您快速了解如何开始编写网络代码。之后,您应该能够从阅读手册页中获取越来越多的信息。
Most of it will consist of reading the documentation for your favourite library, and a basic understanding of man pages.
大部分内容包括阅读您最喜欢的库的文档,以及对手册页的基本了解。
回答by X-Istence
For starters, it would be helpful if you clarify what you mean by "raw". Traditionally this means that you want to craft all of the layer 4 header (TCP/UDP/ICMP... header), and perhaps some of the IP header on your own. For this you will need more than beej's tutorial which has been mentioned my many here already. In this case you want raw IP sockets obtained using the SOCK_RAW argument in your call to socket (see http://mixter.void.ru/rawip.htmlfor some basics).
对于初学者来说,如果您澄清“原始”的含义会有所帮助。传统上,这意味着您希望自己制作所有第 4 层标头(TCP/UDP/ICMP...标头),也许还有一些 IP 标头。为此,您需要的不仅仅是 beej 的教程,我已经在这里提到了很多。在这种情况下,您希望在对 socket 的调用中使用 SOCK_RAW 参数获得原始 IP 套接字(有关一些基础知识,请参阅http://mixter.void.ru/rawip.html)。
If what you really want is just to be able to establish a TCP connection to some remote host such as port 80 on stackoverflow.com, then you probably don't need "raw" sockets and beej's guide will serve you well.
如果您真正想要的只是能够与某些远程主机(例如 stackoverflow.com 上的端口 80)建立 TCP 连接,那么您可能不需要“原始”套接字,beej 的指南将为您提供很好的服务。
For an authoritative reference on the subject, you should really pick up Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition) by Stevens et al.
要获得有关该主题的权威参考,您应该真正阅读 Stevens 等人的 Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition)。
回答by Brian R. Bondy
For TCP client side:
对于 TCP 客户端:
Use gethostbyname to lookup dns name to IP, it will return a hostent structure. Let's call this returned value host.
使用 gethostbyname 查找 dns 名称到 IP,它将返回一个主机结构。我们称此为返回值主机。
hostent *host = gethostbyname(HOSTNAME_CSTR);
Fill the socket address structure:
填充socket地址结构:
sockaddr_in sock;
sock.sin_family = AF_INET;
sock.sin_port = htons(REMOTE_PORT);
sock.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
Create a socket and call connect:
创建一个套接字并调用连接:
s = socket(AF_INET, SOCK_STREAM, 0);
connect(s, (struct sockaddr *)&sock, sizeof(sock))
For TCP server side:
对于 TCP 服务器端:
Setup a socket
设置套接字
Bind your address to that socket using bind.
使用绑定将您的地址绑定到该套接字。
Start listening on that socket with listen
使用 listen 开始侦听该套接字
Call accept to get a connected client. <-- at this point you spawn a new thread to handle the connection while you make another call to accept to get the next connected client.
调用 accept 以获取连接的客户端。<--此时,您生成一个新线程来处理连接,同时再次调用 accept 以获取下一个连接的客户端。
General communication:
一般通讯:
Use send and recv to read and write between the client and server.
使用 send 和 recv 在客户端和服务器之间进行读写。
Source code example of BSD sockets:
BSD 套接字的源代码示例:
You can find some good example code of this at wikipedia.
您可以在wikipedia 上找到一些很好的示例代码。
Further reading:
进一步阅读:
I highly recommend this bookand this online tutorial:
4:
4:
回答by Tom Leys
回答by HappySmileMan
You do this the exact same way you would in regular C, there is no C++ specific way to do this in the standard library.
您可以按照与在常规 C 中完全相同的方式执行此操作,在标准库中没有 C++ 特定的方式来执行此操作。
The tutorial I used for learning this was http://beej.us/guide/bgnet/. It was the best tutorial I found after looking around, it gave clear examples and good explanations of all functions it describes.
我用来学习这个的教程是http://beej.us/guide/bgnet/。这是我环顾四周后发现的最好的教程,它给出了清晰的示例,并对其描述的所有功能进行了很好的解释。
回答by mfontanini
I've been developing libtinsfor the past year. It's a high level C++ packet crafting and sniffing library.
过去一年我一直在开发libtins。它是一个高级 C++ 数据包制作和嗅探库。
Unless you want to reinvent the wheel and implement every protocol's internals, I'd recommend you to use some higher level library which already does that for you.
除非您想重新发明轮子并实现每个协议的内部结构,否则我建议您使用一些已经为您完成的更高级别的库。
回答by Ben Collins
There are tons of references on this (of course, Stevens' book comes to mind), but I found the Beej guideto be incredibly useful for getting started. It's meaty enough that you can understand what's really happening, but it's simple enough that it doesn't take you several days to write a 'hello world' udp client/server.
这方面有大量参考资料(当然,我会想到史蒂文斯的书),但我发现Beej 指南对于入门非常有用。它足够丰富,您可以理解真正发生的事情,但它足够简单,您无需花几天时间即可编写“hello world”udp 客户端/服务器。
回答by Ben Collins
easy:
简单:
#include <sys/socket.h>
#include <sys/types.h>
int socket(int protocolFamily, int Type, int Protocol)
// returns a socket descriptor
int bind(int socketDescriptor, struct sockaddr* localAddress, unsigned int addressLength)
// returns 0
...etc.
...等等。
it's all in sys/socket.h
一切都在 sys/socket.h 中
回答by Ben Collins
Poster, please clarify your question.
海报,请澄清你的问题。
Almost all responses seem to think you're asking for a sockets tutorial; I read your question to mean you need to create a raw socket capable of sending arbitrary IP packets. As I said in my previous answer, some OSes restrict the use of raw sockets.
几乎所有的回复似乎都认为你在要求一个套接字教程;我读到您的问题意味着您需要创建一个能够发送任意 IP 数据包的原始套接字。正如我在之前的回答中所说,某些操作系统限制使用原始套接字。
http://linux.die.net/man/7/raw"Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets."
http://linux.die.net/man/7/raw"只有有效用户 ID 为 0 或 CAP_NET_RAW 能力的进程才允许打开原始套接字。"
回答by Charles Graham
Read Unix Network Programmingby Richard Stevens. It's a must. It explains how it all works, gives you code, and even gives you helper methods. You might want to check out some of his other books. Advanced Programming In The Unix Enviernmentis a must for lower level programming in Unix is general. I don't even do stuff on the Unix stack anymore, and the stuf from these books still helps how I code.
阅读Richard Stevens 的Unix Network Programming。必须的。它解释了它是如何工作的,为您提供代码,甚至为您提供辅助方法。你可能想看看他的其他一些书。 Unix 环境中的高级编程对于 Unix中的低级编程是必须的。我什至不再在 Unix 堆栈上做任何事情,这些书中的内容仍然有助于我编码。