只分析udp,
单独运行clinet,处于connect状态,并没有运行到tunnel这个步骤,单独运行client时没出现虚拟网卡;
单独运行server,处于listen状态,也没运行到tunnel这个步骤,所以单独运行server也不会出现虚拟新网卡。
当server端开启,处于监听状态,这时client请求连接,认证成功后client和server才会进入tunnel执行打开虚拟网卡,
以及读写发送等后续操作。
为深入理解虚拟网卡的建立过程,得深入学习套接字的阻塞和非阻塞问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
| int tunnel(struct vtun_host *host) { ...... if ( (host->persist == VTUN_PERSIST_KEEPIF) && (host->loc_fd >= 0) ) //接口是否已经打开 interface_already_open = 1; if( host->dev ){...} //判断虚拟设备类型 if(!interface_already_open) //虚拟网卡没有打开,则打开之 { ... switch(host->flags & VTUN_TYPE_MASK) { ... case VTUN_TUN: if( (fd[0]=tun_open(dev)) < 0 ) //打开虚拟网卡,获取描述符 { vtun_syslog(LOG_ERR,"Can't allocate tun device %s. %s(%d)", dev, strerror(errno), errno); return -1; } break; } host->loc_fd = fd[0]; //虚拟设备文件描述符存在host->loc_fd中 } switch( host->flags & VTUN_PROT_MASK ) //初始化协议,tcp还是udp { ...... case VTUN_UDP: if( (opt = udp_session(host)) == -1){.....} //进行udp的socket创建等操作 proto_write = udp_write; proto_read = udp_read; } switch( (pid=fork()) ){...} //建立子进程 switch( host->flags & VTUN_TYPE_MASK ) //根据虚拟设备类型,选择相应虚拟设备读写方式 { ..... case VTUN_TUN: set_title("%s tun %s", host->host, dev); dev_read = tun_read; dev_write = tun_write; break; } opt = linkfd(host); ....... }
|