基本套接字API回顾

来源:互联网 发布:应用最广泛的编程语言 编辑:程序博客网 时间:2024/06/06 05:47
基本套接字API回顾

基本套接字API回顾

通常我们要做的第一件事就是获取连接的套接字。可以用socket系统调用来实现。

 

#inclue<sys/socket.h>

int socket(int  domain,int  type,int  protocol);

          返回值:成功时返回套接字描述符,失败时返回-

 

domain是一个常量,用来表示所期望的通信域。最常见的两个域是AF_INET(也就是因特网)AF_LOCAL(AF_UNIX).

 

参数type说明了要创建的套接字类型。

§   SOCK_STREAM——这些套接字提供一个可靠的,全双工,面向连接的字节流。在TCP/IP中就是TCP

§   SOCK_DGRAM——这些套接字提供一个不可靠,尽力而为的数据报服务。在TCP/IP中就是UDP

§   SOCK_RAW——这些套接字允许对IP层的某些数据报进行访问。可用于一些特殊的目的,比如监听ICMP报文。

 

protocol字段说明了应该在套接字上使用那种协议。对于TCP/IP来说,这个字段通常都

由套接字类型隐式说明,参数被设置为零。在某些情况下,比如对原始套接字来说,有几种可能的协议,就要制定希望使用的协议。

 

         对最简单的TCP客户端来说,与对等实体建立会话是需要使用的其他套接字API只有connect一种,connect是用来建立连接的。

 

    #include<sys/socket.h>

         int connect(SOCKET  s,const struct sockaddr  *peer,int  peer_len);

                      返回:成功是返回0,失败时返回-1

参数ssocket调用返回的套接字描述符。参数peer指向一个地址结构,这个结构中装载了期望的对等实体地址和其他一些信息。对AF_INET域来说就是一个sockaddr_in结构。参数peer_lenpeer所指结构的长度。

 

一旦连接建立起来,就可以传送数据了。

#include<sys/socket.h>

int recv(SOCKET  s, void  *buf, size_t  len,int  flags);

int send(SOCKET  s,const void  *buf,size_t  len,int  flags);

                  返回:如成功则为读入或写出的字节数,如出错则为-1

         参数flags的取值通常与系统有关,其值为0或下面列出的一个或多个常值的逻辑或。

l  MSG_DONTROUTE  本标志告诉内核目的主机在某个直接连接的本地网络上,因而无需执行路由表查找。

l  MSG_DONTWAIT  本标志在无需打开相应套接字的非阻塞标志的前提下,把单个I/O操作临时指定为非阻塞,接着执行I/O操作,然后关闭非阻塞标志。

l  MSG_OOB  对于send,本标志指明即将发送带外数据。对于recv本标志指明即将读入的是带外数据而不是普通数据。

l  MSG_PEEK  本标志适用于recvrecvfrom,它允许我们查看已可读取的数据,而且系统不再recvrecvfrom返回后丢弃这些数据。

l  MSG_WAITALL  它告诉内核不要在尚未读入请求数目(len)的字节之前让一个读操作返回。(注:如果发生下列情况之一:(a)捕获一个信号 b)连接被终止 c)套接字发送一个错误,相应的读函数仍有可能返回比所请求的字节数要少的数据。)

TCP来说,这些调用基本上就能满足需求了。但如果使用的是UDP的话,recvfromsendto调用也很有用。

#include<sys/socket.h>

int  recvfrom(SOCKET s , void *buf, size_t len, int flags,

struct sockaddr *from,int *fromlen);

         int  sendto(SOCKET s,const void *buf,size_t len ,int flags,

struct sockaddr *to,int tolen);

         recvfrom函数调用中的参数from指向一个套接字地址结构,内核在这个地址中存储了输入数据报的源地址。这个地址的长度存储在fromlen指向的一个整数中,注意,fromlen是一个指向整数的指针

 

         服务器必须在其知名端口上监听客户连接。这使用listen调用来实现这项功能的,但首先必须将接口地址和知名端口号绑定到它的监听套接字上去。这是用bind调用来实现的。

         #include<sys/socket.h>

         int  bind(SOCKET s ,const struct sockaddr *name,int namelen);

                                                        返回:成功是返回0,失败时返回-1

         参数s是监听套接字的描述符。参数namenamelen提供了要监听的端口和接口。地址通常被设置为INADDR_ANY,说明任何接口都会接受这个连接。如果多宿主主机希望进仅在一个连接上接受连接,它可以指定那个接口的IP地址。

        

用系统调用listen实现的。它唯一的任务就是把套接字标识为监听状态。当主机收到一个连接请求时,内核会搜索监听套接字列表,查找与连接请求中目的地和端口想匹配的那个套接字。

#include<sys/socket.h>

int  listen(SOCKET s, int backlog);

                                               返回:成功是返回0,失败时返回-1

参数s是要标识为监听状态的套接字的描述符。参数backlog是挂起连接的最大数量,它并不是在指定端口上同时可建立连接的最大值,而是排队等待应用程序接受的连接或部分连接的最大数量。

 

最后一个套接字调用是accept系统调用,负责接受已完成连接队列中的连接。连接一旦被接受,就可以用recvsend这样的调用传输数据了。如果运行成功,accept为可以用于数据传输的新套接字返回一个描述符。

#include<sys/socket.h>

SOCKET accept(SOCKET s, struct sockaddr *addr,int *addrlen);

                            返回:如果成功就返回一个连接好的套接字,如果失败就返回-1

参数s是监听套接字的描述符。accept会在addr指向的sockaddr_in结构中返回新连接的对等实体地址。内核将这个结构的长度存放在addrlen指向的整数中。通常我们并不关心对等实体的地址,在这种情况下会将addraddrlen都设置为NULL

原创粉丝点击