我想生成一个网络数据包,通过(例如)端口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) 我的代码在这里遇到了一个真正奇怪的问题.当我使用手动打印语句输出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) 我想更好地了解堆栈和堆如何工作.在比较同一程序的32位和64位编译版本时,我遇到了麻烦.在这两种情况下,我都使用了一个来宾Fedora 15 VM(32和64),gcc用于编译,gdb用于调试,以及相同的主机硬件.有问题的程序非常简单,紧接着如下:
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)
为了空间的利益,我省略了程序的汇编转储; 但是,如果有人认为这可能有助于他们回答我的问题,我很乐意将其纳入其中.
参数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)
然而; 这里没有看到值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)