Socket

来源:互联网 发布:网络诽谤如何取证 编辑:程序博客网 时间:2024/06/11 22:47

 Socket

创建一个socket描述符

int socket(int domain, int type, int protocol);
  • 返回一个套接字描述符;如果出错,则返回 -1。
  • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INETAF_INET6AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
  • type:指定socket类型。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAW。
  • protocol:顾名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

socket配置

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
  • 返回0;如果出现错误,返回 -1 ,并将errno置为相应的错误号。
  • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
  • addr:一个const struct sockaddr * 指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket 时的地址协议族的不同而不同:
    struct sockaddr{   unsigned short sa_family;       /* 地址族, AF_xxx */    char           sa_data[14];     /* 14 字节的协议地址 */};
    /* ipv4对应的是:*/struct sockaddr_in{    sa_family_t    sin_family; /* address family: AF_INET */    in_port_t      sin_port;   /* port in network byte order */    struct in_addr sin_addr;   /* internet address */    unsigned char  sin_zero[8];/* 填充0 以保持与struct sockaddr同样大小 */};/* Internet address. */struct in_addr{    uint32_t       s_addr;     /* address in network byte order */};
    /* ipv6对应的是:*/struct sockaddr_in6{     sa_family_t     sin6_family;   /* AF_INET6 */     in_port_t       sin6_port;     /* port number */     uint32_t        sin6_flowinfo; /* IPv6 flow information */     struct in6_addr sin6_addr;     /* IPv6 address */     uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ };struct in6_addr{     unsigned char   s6_addr[16];   /* IPv6 address */ };
    /* Unix域对应的是: */#define UNIX_PATH_MAX    108struct sockaddr_un{     sa_family_t sun_family;               /* AF_UNIX */     char        sun_path[UNIX_PATH_MAX];  /* pathname */ };
  • addrlen:对应的是地址的长度。

说明:【1】指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换。

           【2】my_addr.sin_port = 0; /* 系统随机选择一个未被使用的端口号 */;
                my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */。

           【3】htonl():把32位值从主机字节序转换成网络字节序;
                     htons():把16位值从主机字节序转换成网络字节序;
                     ntohl():把32位值从网络字节序转换成主机字节序;
                     ntohs():把16位值从网络字节序转换成主机字节序。
           【4】一般不要将端口号置为小于1024的值,因为1到1024是保留端口号。

IP地址转换

  • unsigned long int inet_addr(const char * cp):
    该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:struct sockaddr_in
    ina.sin_addr.s_addr=inet_addr("202.206.17.101")
    该函数成功时,返回转换结果;失败时返回常量INADDR_NONE,该常量 = -1,二进制的无符号整数 -1 相当于255.255.255.255,这是一个广播地址,所以在程序中调用inet_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数inet_aton()。

  • int inet_aton(const char *cp,struct in_addr *inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。
  • char *inet_ntoa(struct in_addr in):将32位二进制形式的IP地址转换为数字点形式的IP地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。

建立连接

int listen(int sockfd, int backlog);
  • 返回0;如果出现错误,返回 -1,并置相应的errno错误码。
  • sockfd:要监听的socket描述字。
  • backlog:相应socket可以排队的最大连接个数;大多数系统缺省值为20。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接;如果出现错误,accept函数返回 -1 并置相应的errno值。
  • sockfd:服务器的socket描述字。
  • addr:指向 struct sockaddr * 的指针,用于返回客户端的协议地址。
  • addrlen:协议地址的长度。
int connect(int sockfd, struct sockaddr *serv_addr,int addrlen);
  • 如果成功就返回0;如果出现错误,就返回 -1 ,并且设置errno为相应的错误码。
  • sockfd:客户端的socket描述字;
  • addr:服务器的socket地址;
  • addrlen:socket地址的长度。

数据传输

#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, const void *buf, size_t count);#include <sys/types.h>#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 成功则返回传送的字节数,失败则返回 -1 。
  • sockfd:传输数据的socket描述符;通过socket()系统调用返回的,也可以是通过accept()系统调用得到的。
  • buf:指向你希望发送的数据的指针。
  • len:数据的字节长度。
  • flags:一般设置为0;
    【1】MSG_OOB 传送的数据以out-of-band 送出。
    【2】MSG_DONTROUTE 取消路由表查询。
    【3】MSG_DONTWAIT 设置为不可阻断运作。
    【4】MSG_NOSIGNAL 此动作不愿被SIGPIPE信号中断。

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 返回实际上接收的字节数,当出现错误时,返回 -1 并置相应的errno值。
  • sockfd:接受数据的socket描述符。
  • buf:存放接收数据的缓冲区。
  • len:缓冲的长度。
  • flags:一般去0。
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,               const struct sockaddr *dest_addr,               socklen_t addrlen);
  • 返回实际发送的数据字节长度或在出现发送错误时返回 -1 。
  • dest_addr:目的机的IP地址和端口号信息。
  • addrlen:常常被赋值为sizeof (struct sockaddr)。
ssize_t recvfrom(int sockfd, void *buf, size_t len,                  int flags, struct sockaddr *src_addr,                 socklen_t *addrlen);
  • 返回接收到的字节数;当出现错误时返回 -1 ,并置相应的errno。
  • src_addr:一个struct sockaddr类型的变量,该变量保存源机的IP地址及端口号。
  • addrlen:常置为sizeof (struct sockaddr)。
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
struct msghdr{    void *msg_name;            /*Address to send to /receive from . */    socklen_t msg_namelen;     /* Length of addres data */    strcut iovec * msg_iov;    /* Vector of data to send/receive into */    size_t msg_iovlen;         /* Number of elements in the vector */    void * msg_control;        /* Ancillary dat */    size_t msg_controllen;     /* Ancillary data buffer length */    int msg_flags;             /* Flags on received message */ };
  • 成功则返回发送的字符数;失败则返回 -1 ,错误原因存于errno中。
  • msg:指向欲连线的数据结构内容。
  • flags:一般默认为0。
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
  • 成功则返回接收到的字符数;失败则返回 -1 ,错误原因存于errno中。
  • msg:参考sendmsg函数。
  • flags:一般设置为0。

结束传输

int close(int fd);

         也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。
   int shutdown(int sockfd,int how);
   Sockfd是需要关闭的socket的描述符。参数how 允许为shutdown操作选择以下几种方式:
   【1】0-------不允许继续接收数据
   【2】1-------不允许继续发送数据
   【3】2-------不允许继续发送和接收数据,
   【4】均为允许则调用close ()
   shutdown在操作成功时返回0,在出现错误时返回-1并置相应errno。