linux tcp server accept,TCP/UDP网络编程入门教程之六:TCP Server端——创建“通讯”嵌套字...

这里的“通讯”加上了引号,是因为实际上所有的socket都有通讯的功能,只是在我们的例子中,之前那个socket只负责listen,而这个socket负责接受信息并echo回去。

我们现看看这个函数:

C++代码boolTcpServer::isAccept()

{

unsigned intclntAddrLen =sizeof(clntAddr);

if( (communicationSock = accept(listenSock, (sockaddr*)&clntAddr, &clntAddrLen)) 

returnfalse;

} else{

std::cout <

returntrue;

}

}

用accept()创建新的socket

在我们的例子中,communicationSock实际上是用函数accept()创建的。

C++代码intaccept(intsocket,structsockaddr* clientAddress, unsignedint* addressLength);

在Linux中的实现为:

C++代码/* Await a connection on socket FD.

When a connection arrives, open a new socket to communicate with it,

set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting

peer and *ADDR_LEN to the address's actual length, and return the

new socket's descriptor, or -1 for errors.

This function is a cancellation point and therefore not marked with

__THROW.  */

externintaccept (int__fd, __SOCKADDR_ARG __addr,

socklen_t *__restrict __addr_len);

这个函数实际上起着构造socket作用的仅仅只有第一个参数(另外还有一个不在这个函数内表现出来的因素,后面会讨论到),后面两个指针都有副作用,在socket创建后,会将客户端sockaddr的数据以及结构体的大小传回。

当程序调用accept()的时候,程序有可能就停下来等accept()的结果。这就是我们前一小节说到的block(阻塞)。这如同我们调用std::cin的时候系统会等待输入直到回车一样。accept()是一个有可能引起block的函数。请注意我说的是“有可能”,这是因为accept()的block与否实际上决定与第一个参数socket的属性。这个文件描述符如果是block的,accept()就block,否则就不block。默认情况下,socket的属性是“可读可写”,并且,是阻塞的。所以,我们不修改socket属性的时候,accept()是阻塞的。

accept()的另一面connect()

accept()只是在server端被动的等待,它所响应的,是client端connect()函数:

C++代码intconnect(intsocket,structsockaddr* foreignAddress, unsignedintaddressLength);

虽然我们这里不打算详细说明这个client端的函数,但是我们可以看出来,这个函数与之前我们介绍的bind()有几分相似,特别在Linux的实现中:

C++代码/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).

For connectionless socket types, just set the default address to send to

and the only address from which to accept transmissions.

Return 0 on success, -1 for errors.

This function is a cancellation point and therefore not marked with

__THROW.  */

externintconnect (int__fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

connect() 也使用了const的sockaddr,只不过是远程电脑上的而非bind()的本机。

accept()在server端表面上是通过listen socket创建了新的socket,实际上,这种行为是在接受对方客户机程序中connect()函数的请求后发生的。综合起看,被创建的新socket实际上包含了listen socket的信息以及客户端connect()请求中所包含的信息——客户端的sockaddr地址。

新socket与sockaddr的关系

accept()创建的新socket(我们例子中的communicationSock,这里我们简单用newSock来带指)首先包含了listen socket的信息,所以,newSock具有本机sockaddr的信息;其次,因为它响应于client端connect()函数的请求,所以,它还包含了clinet端sockaddr的信息。

我们说过,stream流形式的TCP协议实际上是建立起一个“可来可去”的通道。用于listen的通道,远程机的目标地址是不确定的;但是newSock却是有指定的本机地址和远程机地址,所以,这个socket,才是我们真正用于TCP“通讯”的socket。

inet_ntoa()

C++代码#include 

/* Convert Internet number in IN to ASCII representation.  The return value

is a pointer to an internal array containing the string.  */

externchar*inet_ntoa (structin_addr __in) __THROW;

对于这个函数,我们可以作为一种,将IP地址,由in_addr结构转换为可读的ASCII形式的固定用法。

除非特别注明,鸡啄米文章均为原创

2015年7月16日

作者:鸡啄米

浏览:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值