stefenlin 发表于 2007-5-9 12:31

(电子,计算机)请教个TCP/IP协议的问题

在TCP/IP协议中,发送完一个包,如果发送成功都可以收到个ACK,请教下在Linux系统下,哪个文件哪个参数可以直接反应出ACK收到的状态或数量(时实反应出的)?
非常感谢。

eisenstange 发表于 2007-5-9 13:21

<Socket.h>?

eisenstange 发表于 2007-5-9 13:53

0       4       810         16            24            32
-------------------------------------------------------------------
|               源端口          |               目的端口      |
-------------------------------------------------------------------
|                               序列号                        |
------------------------------------------------------------------
|                               确认号                        |
------------------------------------------------------------------
|      |            |U|A|P|S|F|                               |
|首部长度| 保留       |R|C|S|Y|I|       窗口                  |
|      |            |G|K|H|N|N|                               |
-----------------------------------------------------------------
|               校验和          |               紧急指针      |
-----------------------------------------------------------------
|                     选项                  |    填充字节   |
-----------------------------------------------------------------

TCP的结构在中定义为:
struct tcphdr
{
    u_int16_t source;
    u_int16_t dest;
    u_int32_t seq;
    u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int16_t res1:4;
    u_int16_t doff:4;
    u_int16_t fin:1;
    u_int16_t syn:1;
    u_int16_t rst:1;
    u_int16_t psh:1;
    u_int16_t ack:1;
    u_int16_t urg:1;
    u_int16_t res2:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
    u_int16_t doff:4;
    u_int16_t res1:4;
    u_int16_t res2:2;
    u_int16_t urg:1;
    u_int16_t ack:1;
    u_int16_t psh:1;
    u_int16_t rst:1;
    u_int16_t syn:1;
    u_int16_t fin:1;
#endif
    u_int16_t window;
    u_int16_t check;
    u_int16_t urg_prt;
};      

source发送TCP数据的源端口
dest接受TCP数据的目的端口

seq标识该TCP所包含的数据字节的开始序列号

ack_seq确认序列号,表示接受方下一次接受的数据序列号.

doff数据首部长度.和IP协议一样,以4字节为单位.一般的时候为5

urg如果设置紧急数据指针,则该位为1

ack如果确认号正确,那么为1

psh如果设置为1,那么接收方收到数据后,立即交给上一层程序

rst为1的时候,表示请求重新连接

syn为1的时候,表示请求建立连接

fin为1的时候,表示亲戚关闭连接

window窗口,告诉接收者可以接收的大小

check对TCP数据进行较核

urg_ptr如果urg=1,那么指出紧急数据对于历史数据开始的序列号的偏移值

关于TCP协议的详细情况,请查看 RFC793

eisenstange 发表于 2007-5-9 14:04

/* creat the raw socket for icmp */

if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket");
exit(2);
}

你可以把IPPROTO_ICMP改成你要得协议

/* set destination host information */

bzero(&it, sizeof(it));
it.sin_family = AF_INET;

其中it的结构 struct sockaddr_in it; /* destination host information */

/* check host format */

if ( ( lHostIp = inet_addr(host) ) != INADDR_NONE ) {
/* is available ip adress */
it.sin_addr.s_addr = lHostIp;
strcpy( dst_host, host );
} else if ( h = gethostbyname(host) ) {
/* is available host name */
/* from hosts file of local host */
/* or from DNS */
bcopy(h->h_addr, &it.sin_addr, h->h_length);
sprintf( dst_host, "%s (%s)", host,
inet_ntoa(it.sin_addr) );
} else {
/* bad ip adress or host name */
/* exit */
fprintf( stderr, "bad IP or host\n" );
exit(3);
}

//////////////////////////////////////

char buf;
int iPacketSize;

/* make the icmp header information */

ICMPHEAD *pIcmpHead = (ICMPHEAD *)buf;
pIcmpHead->icmp_type = ICMP_ECHO;
pIcmpHead->icmp_code = 0;
pIcmpHead->icmp_id = seq;
pIcmpHead->icmp_seq = seq;
pIcmpHead->icmp_chksum = 0;

/* store time information as icmp packet content, 4 bytes */
/* u may store other information instead */

*((long *)pIcmpHead->icmp_data) = time_now();

iPacketSize = ICMP_HEADSIZE + 4; /* icmp packet length */

/* icmp header check sum */

pIcmpHead->icmp_chksum = ChkSum((u_short *)pIcmpHead,
iPacketSize );

/* remember the time when send for calculate round trip time */
lSendTime = time_now();

/* send the icmp packet to des host */
if ( sendto(sock, buf, iPacketSize, 0, (struct sockaddr *)&it,
sizeof(it) ) < 0) {
perror("send failed");
exit(6);
}

/////////////////////////////////////////////

其中 Sendto是发送函数

同样当你接受到报文以后,再手动的用上一贴中定义的包结构来拆分从套接字缓存区得到的数据,并拆出ACK位。下面是一个ICMP报文拆包的例子

/* block to received echo back datagram */

size = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *)&it, &namelen);
if (size == -1 && errno == EINTR) {
/* receive error or system call */
/* interrupted */
continue;
}

/* calculate the round trip time, */
/* time when receive minus time when send */

delta = (int)((time_now() - lSendTime)/1000);

/* get echo back packet and check its ip header */

pIpHead = (IPHEAD *)buf;

/* get the ip packet lenth */
/* if too small, not the icmp echoreply packet */
/* give it up */

iIpHeadLen = (int)((pIpHead->ip_verlen & 0x0f) << 2);
if (size < iIpHeadLen + ICMP_HEADSIZE) {
continue;
}
ttl = pIpHead->ip_ttl; /* time to live param */

/* get the icmp header information */
pIcmpHead = (ICMPHEAD *)(buf + iIpHeadLen);

/* not icmp echo reply packet, give it up */
if (pIcmpHead->icmp_type != ICMP_ECHOREPLY) {
continue;
}

/* not proper icmp sequent number, give it up */
if (pIcmpHead->icmp_id != seq || pIcmpHead->icmp_seq != seq) {
continue;
}

stefenlin 发表于 2007-5-9 15:20

谢谢,我仔细看看哦。$支持$ $支持$ $支持$

瓜瓜乐 发表于 2007-5-10 10:02

$支持$ $支持$ :)

飞来一头猪 发表于 2007-5-10 15:31

$支持$ $支持$ :D :D 版主是高人啊!!!!$高$
页: [1]
查看完整版本: (电子,计算机)请教个TCP/IP协议的问题