在学习《unix环境高级编程》第二版的过程中,书中给出了一些套接字在应用过程中常见的代码模块,分别是:
①服务器的套接字初始化
②客户端建立到服务器的连接
③面向连接的,客户端接收数据的代码
④面向连接的,服务器发送数据的代码
⑤无连接的,客户端接收数据的代码
⑥无连接的,服务器发送数据的代码
下面分别对这几个代码模块进行说明。
①服务器套接字初始化:主要做的事:通过地址、类型、和长度,用个socket函数得到一个相对应网络环境的套接字描述符,然后利用bind将该套接字描述符与地址进行绑定。
如果是有连接的,还需要利用listen函数监听该套接字描述符,用于声明我开始监听客户请求了。
源代码如下:
②客服端到服务器的连接。做的主要工作:就是利用connect将客户端的套接字文件描述符sockfd连接到要连接的服务器的地址上去,源代码利用了一个技巧指数补偿算法,如果连接不成功,睡眠一定时间后再次进行连接,而且每次睡眠的时间会递增。注意如果这个sockfd没有和一个地址绑定的话,在调用connect时自动绑定一个地址。
源代码:
③面向连接的,客户端的代码。主要干的事情是:首先利用getaddrinfo函数得到所要连接的服务的地址。然后利用socket建立一个与该地址环境相同的套接字描述符,然后利用连接代码模块建立到服务器的连接,再然后利用recv函数接受套接字描述符所指服务的数据到缓冲区。此后可以利用write函数将该缓冲区的数据写到文件中。
源代码:
④面向连接,服务器代码:主要做的事情是,首先利用gethostname获得主机名,然后将所要的服务进程设定为守护进程,再然后利用getaddrinfo获得地址,再然后利用服务器初始化代码,获得套接字描述符,得到套接字描述符后,利用accept开始监听端口看是否有服务请求返回另外一个套接字描述符,利用popen建立一个服务的输出到父进程的管道,利用fgets将该输出写到缓冲区,在利用send将该缓冲区数据发送到刚才返回的套接字描述符。
源代码:
另外一种面向连接的服务器:其区别部分主要是server函数部分,上面代码serve的思路是利用管道,将管道输出传到父进程的一个文件描述符,然后再对该文件描述符进行相关操作。而下面代码的主要思路是:利用了在某些情况下,套接字可以看做为文件描述符。首先是服务器进行accept等待客户请求,然后fork一个子进程,接着并不是马上进行服务程序,而是进行了一些文件描述符的复制工作,即将标准输出和标准出错文件描述符指向套接字所指向的文件,即利用dup2将套接字描述符的特性复制到了标准输出,和标准出错。这样子程序的标准输出和标准出错就直接指定到网络中的发送装备上去了。
源代码如下:
⑤无连接,客户端:主要思路:利用getaddrinfo获取服务器端口地址,然后利用socket得到一个套接字描述符,再然后利用sendto向服务器发送一个字节(这个主要目的是告之服务器是由哪个客户端申请服务的),接着利用recvfrom进行接收数据,注意为了防止永久阻塞,在recvfrom函数前加了个alarm函数。
源代码:
⑥无连接,服务器:主要思路:利用gethostname获得服务器名称,然后初始化守护进程,然后利用getaddrinfo获取地址,再然后利用初始化模块获得套接字描述符。接着利用recvfrom用来接收客户发送来的数据,并将客户端的地址记录下来(这才是目的),然后利用popen建立管道,返回文件描述符fd,利用fgets写到缓冲区,用sendto发送出去。
源代码:
小结:无论是客户端还是服务器都需要利用getaddinfo获取服务端口地址,获取这个地址有两个目的:
①告之网络环境,利用socket生成套接字描述符
②用作连接发送数据目的地址用。