Linux内核--网络栈实现分析(九)--传输层之UDP协议(下)

发表于:2013-1-05 09:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:闫明    来源:51Testing软件测试网采编

  注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析、”(下)“表示分析是从上向下分析。

  上篇分析了应用层经过BSD socket层到INET socket层的函数调用关系和数据的处理流程,INET层会调用具体的传输层协议,还是以UDP协议为例

  udp_write()函数

static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
   unsigned flags)
{
 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
}

  在分析udp_sendto()函数之前,先了解一下sockaddr_in结构,这是标准的网络接口地址结构的定义

struct sockaddr_in {
  short int  sin_family; /* Address family 地址族 */
  unsigned short int sin_port; /* Port number 端口号  */
  struct in_addr sin_addr; /* Internet address 网络地址 */

  /* Pad to size of `struct sockaddr'. */
  unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int) -
   sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero __pad  /* for BSD UNIX comp. -FvK */

  udp_sentdto()函数

static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
    unsigned flags, struct sockaddr_in *usin, int addr_len)
{
 struct sockaddr_in sin;
 int tmp;

 /*
  * Check the flags. We support no flags for UDP sending
  */
 if (flags&~MSG_DONTROUTE)
    return(-EINVAL);
 /*
  * Get and verify the address.
  */
 
 if (usin) //如果usin不是空
 {
  if (addr_len < sizeof(sin))
   return(-EINVAL);
  memcpy(&sin,usin,sizeof(sin));
  if (sin.sin_family && sin.sin_family != AF_INET)
   return(-EINVAL);
  if (sin.sin_port == 0)
   return(-EINVAL);
 }
 else //usin为空
 {
  if (sk->state != TCP_ESTABLISHED)
   return(-EINVAL);
  sin.sin_family = AF_INET;//协议族
  sin.sin_port = sk->dummy_th.dest;//目的端口
  sin.sin_addr.s_addr = sk->daddr;//目的地址
   }
 
   /*
    * BSD socket semantics. You must set SO_BROADCAST to permit
    * broadcasting of data.
    */
   
   if(sin.sin_addr.s_addr==INADDR_ANY)//目的地址是全0地址,对应当前主机
    sin.sin_addr.s_addr=ip_my_addr();//将目的地址设为当前主机的网络地址
    
   if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
      return -EACCES;   /* Must turn broadcast on first */

 sk->inuse = 1;

 /* Send the packet. */
 tmp = udp_send(sk, &sin, from, len, flags);//调用udp_send()真正的发送数据

 /* The datagram has been sent off.  Release the socket. */
 release_sock(sk);
 return(tmp);
}

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号