您的位置:首页 > 编程语言

netcat源代码分析,udp模式(1)服务端如何得到客户端的ip地址和端口号?

2013-05-14 18:16 351 查看


/* UDP is a speeeeecial case -- we have to do I/O *and* get the calling

   party's particulars all at once, listen() and accept() don't apply.

   At least in the BSD universe, however, recvfrom/PEEK is enough to tell

   us something came in, and we can set things up so straight read/write

   actually does work after all.  Yow.  YMMV on strange platforms!  */

  if (o_udpmode) {

    x = sizeof (SA);        /* retval for recvfrom */

    arm (2, o_wait);        /* might as well timeout this, too */

    if (setjmp (jbuf) == 0) {    /* do timeout for initial connect */

fprintf(stderr,"  0remend->sin_addr.sin_port = %u \n",ntohs(remend->sin_port));

fprintf(stderr,"  0remend->sin_addr.sin_addr = %s \n",inet_ntoa(remend->sin_addr));

      rr = recvfrom        /* and here we block... */

    (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x);

fprintf(stderr,"  1remend->sin_addr.sin_port = %u \n",ntohs(remend->sin_port));

fprintf(stderr,"  1remend->sin_addr.sin_addr = %s \n",inet_ntoa(remend->sin_addr));

Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))

    } else

      goto dol_tmo;        /* timeout */

    arm (0, 0);

/* I'm not completely clear on how this works -- BSD seems to make UDP

   just magically work in a connect()ed context, but we'll undoubtedly run

   into systems this deal doesn't work on.  For now, we apparently have to

   issue a connect() on our just-tickled socket so we can write() back.

   Again, why the fuck doesn't it just get filled in and taken care of?!

   This hack is anything but optimal.  Basically, if you want your listener

   to also be able to send data back, you need this connect() line, which

   also has the side effect that now anything from a different source or even a

   different port on the other end won't show up and will cause ICMP errors.

   I guess that's what they meant by "connect".

   Let's try to remember what the "U" is *really* for, eh?

*/

    rr = connect (nnetfd, (SA *)remend, sizeof (SA));

    goto whoisit;

  } /* o_udpmode */

函数原型:ssize_t recvfrom(int sockfd,void *buf,int len,unsigned int flags, struct sockaddr *from,socket_t *fromlen); ssize_t 相当于 int,socket_t 相当于int ,这里用这个名字为的是提高代码的自说明性。

参数:

sockfd:标识一个已连接套接口的描述字。 

buf:接收数据缓冲区。 

len:缓冲区长度。 

flags:调用操作方式。

MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。

from:(可选)指针,指向装有源地址的缓冲区。 

fromlen:(可选)指针,指向from缓冲区长度值。

返回值:

如果正确接收返回接收到的字节数,失败返回0.

G:\nc\nc115-debug>nc -ulp 66

in res_init

after recycle

after go: x now , optarg 0 optind 3

curport = (null)

in dolisten lp = 66

in doconnect

in doconnect ,listen socket nnetfd = 1864.

in dolisten nnetfd = 1864

in arm num = 2 stdhnd = 7

handle is 7
  0remend->sin_addr.sin_port = 0

  0remend->sin_addr.sin_addr = 0.0.0.0

  1remend->sin_addr.sin_port = 2095

  1remend->sin_addr.sin_addr = 127.0.0.1

dolisten/recvfrom ding, rr = 2, netbuf d

in arm num = 0 stdhnd = 7

handle is 7

remend->sin_port = 1837

bigbuf_net = 127.0.0.1

in dolisten , socket nnetfd = 1864.

got 2 from the net, errno 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐