1、首先main函数里面,利用getopt 等函数检测命令行参数(关于波特率、主机、端口等信息。并对相关变量进行赋值)。
2、 如果指定了-a 参数,则利用-a参数的 host 信息,利用addrinfo 结构体 和 getaddrinfo等函数获得 地址和端口的信息。
3、利用 socket 函数和 addrinfo 里面的信息创建 socket,返回 fd。 SOCKET socket( int af, int type, int protocol ); socket函数的介绍在下面。
4、然后利用connect 函数创建 socket 连接。connect函数下面有介绍。
5、如果 host=NULL,则打开 -s 参数指定的设备名称,保存在变量siodev 中,linux中为 ttyS0.
slipfd = devopen(siodev, O_RDWR | O_NONBLOCK)。
devopen函数调用open函数打开 /dev/ttyS0 文件,同时指定 flags ,并返回文件描述符。
6、利用slip_send(int fd, unsigned char c) 函数发送字符。此函数中,将要发送的字符 c 保存到 slip_buf[] 数组中。
unsigned char slip_buf[2000];
slip_flushbuf(int fd) 函数:
用n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin));
用 write函数将slip_buf 里面的字符 写到文件描述符里面 slipfd 。
7、然后利用 inslip = fdopen(slipfd, "r");把 文件句柄与一个流 相关联。 返回 一个 FILE 结构体类型的指针FILE * 到 inslip。
8、通过 tunfd = tun_alloc(tundev, tap); 打开网络虚拟设备 TUN 和TAP(不懂)。
一、此c函数文件中设计到很多linux c的函数和变量,学习并记录。
1、 fd_set
select()函数主要是建立在fd_set类型的基础上的。fd_set(它比较重要所以先介绍一下)是一组文件描述字(fd)的集合,它用一位来表示一个fd(下面会仔细介绍),对于fd_set类型通过下面四个宏来操作:
过去,一个fd_set通常只能包含<32的fd(文件描述字),因为fd_set其实只用了一个32位矢量来表示fd;现在,UNIX系统通常会 在头文件<sys/select.h>中定义常量FD_SETSIZE,它是数据类型fd_set的描述字数量,其值通常是1024,这样就能表示<1024的fd。根据fd_set的位矢量实现,我们可以重新理解操作fd_set的四个宏:
注意fd的最大值必须小于FD_SETSIZE。
2、setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
函数名: setvbuf 功 能: 把缓冲区与流相关 用 法: int setvbuf(FILE *stream, char *buf, int type, unsigned size); 参数:stream :指向流的指针 ; buf : 期望缓冲区的地址; type : 期望缓冲区的类型: _IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数 据。 _IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据。 _IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区。 size : 缓冲区内字节的数量。
3、getopt函数 和optarg 变量
此函数和变量结合起来,用来解析命令行参数。
4、addrinfo 结构 注意在ws2tcpip.h文件中定义
The addrinfo structure is used by the getaddrinfo function to hold host address information.
typedef struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char* ai_canonname; struct sockaddr* ai_addr; struct addrinfo* ai_next; } ADDRINFOA, *PADDRINFOA; 5、 SOCKET socket( int af, int type, int protocol );应用程序调用socket函数来创建一个能够进行网络通信的套接字。 第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET; 第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM、原始套接字SOCK_RAW(WinSock接口并不适用某种特定的协议去封装它,而是由程序自行处理数据报以及协议首部); 第三个参数指定应用程序所使用的通信协议。 该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回 INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结 构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结 构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。 下面是一个创建流套接字的例子: struct protoent *ppe; ppe=getprotobyname("tcp"); SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);
6、int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址。结构sockaddr请参考bind()。参数addrlen为sockaddr的结构长度。
7、 函数名: fdopen 功 能: 把流与一个文件句柄相接 用 法: FILE *fdopen(int handle, char *type);
8、TUN 与 TAP
在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备。不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行与操作系统上的软件提供与硬件的网络设备完全相同的功能。
TAP 等同于一个以太网设备,它操作第二层数据包如以太网数据帧。TUN模拟了网络层设备,操作第三层数据包比如IP数据封包。
操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TNU/TAP设备发送数据。在后种情况下,TUN/TAP设备向操作系统的网络栈投递(或“注入”)数据包,从而模拟从外部接受数据的过程。
TUN/TAP被用于:
9、ssystem(const char *fmt, ...)