小编she*_*ept的帖子

如何使用C/C++生成网络数据包

我想生成一个网络数据包,通过(例如)端口123发送到NTP服务器,以便我可以接收和解析返回的数据包.目标是更好地了解网络系统如何生成,读取和回复数据包.

(1)是否应该使用结构来生成数据包?

(2)我不确定如何正确填充结构中的各个字段; 例如,是否应使用十六进制值设置源和目标IP地址?还是有一种更人性化的方式?

(3)然后,一旦填充了字段,结构是否可以通过UDP连接通过send()/ write()发送到NTP服务器?(或TCP,协议是否需要它)

我的方法合理吗?我一直在阅读NTP RFC,但我仍然不确定我的客户端应该向服务器发送什么(例如IP地址;网络层标头不应该这样做吗?)我已经建模了这个NTP在RFC 5905的附录A中的"传输"示例之后的结构.如果我的问题措辞不够或太长,我会道歉.预先感谢您的任何帮助.下面的代码示例借用了RFC 5905中的示例代码.

typedef unsigned long ipaddr;       //32 bits (4 bytes)
typedef signed char s_char;     //character type as number, -128..127
typedef unsigned int tdist;     //character type as number, 0..255
typedef unsigned long long tstamp;  //64 bits (8 bytes)
typedef unsigned long digest;       //32 bits (4 bytes)

struct Ntp {
    ipaddr  dstaddr;
    ipaddr  srcaddr;
    char    version;
    char    leap;
    char    mode;
    char    stratum;
    char    poll;
    s_char  precision;
    tdist   rootdelay;
    tdist   rootdisp;
    char    refid;
    tstamp  reftime; …
Run Code Online (Sandbox Code Playgroud)

c c++ udp client-server ntp

6
推荐指数
1
解决办法
1987
查看次数

指针分割错误

我的代码在这里遇到了一个真正奇怪的问题.当我使用手动打印语句输出int*primesArr的值时它(貌似)起作用,但如果我尝试使用for循环它会失败.我通过gdb运行它,发现它在我将数组中的下一个单元格设置为值'k'的地方崩溃,这只发生在数字为素数时.第一次迭代成功(即2设置为primesArr [0]),然后程序Segfaults尝试增加数组.但这只在使用for循环时才会发生.当我创建单独的打印语句时,我的程序按预期工作.我不确定如何/为什么我在访问使用for-loop时未被占用的内存.我确定我在某个地方犯了一些业余错误,这可能与我如何通过我的指针有关...但我无法确定它的确切根.我很感激任何帮助,并提前感谢你.

#include<stdio.h>

int genPrimes(int seed, int *test){
    int inNumPrimes=0;
    for(int k=0; k<=seed; k++){//k is number being checked for primeness
        int cnt=0;
        for(int i=1; i<=k; i++){//'i' is num 'k' is divided by
            if(k%i == 0){
                cnt++;
                if(cnt > 2){
                    break;
                }
                }else{
            }

        }
        if(cnt == 2){
            printf("%i IS PRIME\n",k);
            *test=k;
            test++;//according to gdb, the problem is somewhere between here
            inNumPrimes++;//and here. I'd wager I messed up my pointer somehow
        }
        //printf("%i\n",k);
    }
    return inNumPrimes;
}

int main(){
    int outNumPrimes=0; …
Run Code Online (Sandbox Code Playgroud)

c++ parameter-passing segmentation-fault

2
推荐指数
2
解决办法
187
查看次数

为什么本程序的32位和64位编译版本以这种方式填充内存?

我想更好地了解堆栈和堆如何工作.在比较同一程序的32位和64位编译版本时,我遇到了麻烦.在这两种情况下,我都使用了一个来宾Fedora 15 VM(32和64),gcc用于编译,gdb用于调试,以及相同的主机硬件.有问题的程序非常简单,紧接着如下:

C程序

void function(int a, int b, int c, int d){
    int value;
    char buffer[10];

    value = 1234;
    buffer[0] = 'A';
}

int main(){
    function(1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)

为了空间的利益,我省略了程序的汇编转储; 但是,如果有人认为这可能有助于他们回答我的问题,我很乐意将其纳入其中.

32位编译程序:

参数4(0xbffff3e4),3(0xbffff3e0),2(0xbffff3dc)和1(0xbffff3d8)首先被压入堆栈.接下来的指令的位置以下的呼叫为函数() -或返回地址-被放置在堆(0x080483d1)上.接下来,前一个堆栈(0xbffff3e8)的基指针的值被推送到堆栈.

(gdb) x/16xw $esp
0xbffff3c0: 0x00000000  0x410759c3  0x4105d237  0x00000000
0xbffff3d0: 0xbffff3e8  0x080483d1  0x00000001  0x00000002//pointers
0xbffff3e0: 0x00000003  0x00000004  0x00000000  0x4105d413//followed by params
0xbffff3f0: 0x00000001  0xbffff484  0xbffff48c  0x41040fc4
Run Code Online (Sandbox Code Playgroud)

64位编译程序:

然而; 这里没有看到值4,3,2和1.我只能看到,无论我看到的堆栈多远,都是返回地址(0x4004ae)和先前堆栈帧的基指针(0x7fffffffe210).

(gdb) x/16xg $rsp
0x7fffffffe200: 0x00007fffffffe210  0x00000000004004ae //pointers
0x7fffffffe210: 0x0000000000000000  0x00000036d042139d
0x7fffffffe220: 0x0000000000000000  0x00007fffffffe2f8
0x7fffffffe230: …
Run Code Online (Sandbox Code Playgroud)

linux compiler-construction x86 stack x86-64

1
推荐指数
1
解决办法
247
查看次数