Linux支持伯克利(BSD)风格的套接字编程。它同时支持面向连接和无连接类型的套接字。在面向连接的通讯中,服务器和客户机在交换数据之前要先建立一个连接。在无连接通讯中数据被作为信息的一部分被交换。无论哪一种方式,服务器总是最先启动,把自己绑定(Banding)在一个套接字上然后侦听信息。服务器究竟怎样试图去侦听就得依靠你编程所设定的连接类型了。
3.1 socket()函数
3.2 bind()函数
最后注意有关bind()的是:有时候你并不一定要调用bind()来建立网络连接。比如你只是想连接到一个远程主机上面进行通讯,你并不在乎究竟是用自己机器上的哪个端口进行通讯(比如 Telnet),那么你可以简单的直接调用connet()函数,connect()将自动寻找本地机器上的一个未使用的端口,然后调用bind()来将其socket绑定到那个端口上。
3.3 connect()函数
再次强调,一定要检测connect()的返回值:如果发生了错误(比如无法连接到远程主机,或是远程主机的指定端口无法进行连接等)它将会返回错误值-1。全局变量errno将会存储错误代码。基本上,我们并不在乎我们本地用什么端口来通讯,是不是?我们在乎的是我们连到哪台主机的哪个端口上。Linux内核自动为我们选择了一个没有被使用过的本地端口。
3.4 listen()函数
listen()函数是等待别人来连接,进行系统侦听请求的函数。当有人连接你的时候,需要做两步:通过listen()函数等待连接请求,然后使用accept()函数来处理。
如果你想在一个端口上接受外来连接请求的话,那么函数的调用顺序为:
socket();
bind();
listen();
/* 在这里调用accept()函数 */
......
3.5 accept()函数
如果accept()失败的话,accept()函数会返回一个-1来表明调用失败,同时全局变量errno将会存储错误代码。
面向连接的通信中客户机要做如下一些事:
调用一个socket()函数创建一个套接字;
调用一个connect()函数试图连接服务;
如果连接成功调用,wirte()函数请求数据,调用read()函数接收引入的应答。
3.6 send()、recv()函数
这两个函数是最基本的。
send()函数在调用后会返回它真正发送的数据的长度。
注意:send()所发送的数据可能少于你给它的参数所制定的长度!
因为,如果你给send()的参数中包含的数据的长度远远大于send()所能一次发送的数据,则send()函数只能发送它所能发送的最大数据长度,然后它相信你会把剩下的数据再次调用它来进行第二次发送。所以,记住,如果send()函数的返回值小于len的话,则你需要再次发送剩下的数据。幸运的是,如果包足够小(小于IK),那么send()一般都会一次发送光的。
3.7 sendto()、recvfrom()函数
这两个函数是进行无连接的UDP通讯时使用的。使用这两个函数,则数据会在没有建立过任何连接的网络上传输。因为数据报套接字无法对远程主机进行连接,想想我们在发送数据前需要知道些什么呢?
PS: 取得远程主机的IP地址和端口!
注意:如果你使用connect()连接到了一个数据报套接字的服务器程序上,那么你就可以使用send()和recv()函数来传输你的数据,不要以为你在使用一个流式的套接字,你所使用的仍然是一个使用者数据报的套接字,只不过套接字界面在send()和recv()的时候自动帮助你加上了目标地址,目标端口的信息。