首页 > 代码库 > socket编程之三:socket网络编程中的常用函数

socket编程之三:socket网络编程中的常用函数

这节本来打算先给出常用函数介绍,再给两个代码实例,写着写着发现越来越长,决定把代码放在下一节。

本节内容持续更新......

1 socket()函数

原型:

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

描述:

类似打开一个文件,返回一个socket描述符,唯一标识一个socket,后面相应的操作都是这用这个socket描述符。

参数:

domain:协议族,常用的协议族有AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE等;

协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定列要使用ipv4与16位端口号组合;

AF_LOCAL决定了要用一个绝对路径名作为地址。

type:socket类型,常用的socket类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET等;

socket类型决定列要使用的传输协议,如SOCK_STREAM对应TCP,SOCK_DGRAM对应UDP.

protocol:协议,常用的有:IPPROTO_TCP、IPPTOTO_UDP、IPPTOTO_SCTP等;

他们分别对应TCP传输协议、UDP传输协议、SCTP传输协议。

返回值:

成功返回一个socket描述符,失败返回-1。


2 bind()函数

原型:

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);

描述:

将socket绑定到一个地址,包括IP和端口号。

参数:

sockfd:通过socket返回的一个唯一的描述符;

addr:要绑定给sockfd的地址,是一个结构体指针,这个结构体地址根据socket的地址族不同而不同,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 */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};
addrlen:对应地址的长度,通过sizeof获得

返回值:

成功返回0,失败返回-1。


3 listen()函数

原型:

int listen(int sockfd, int backlog);

描述:

让socket处于监听状态

参数:

sockfd:要设置为监听状态的socket描述符

backlog:可以排队的最大链接个数

返回值:

成功返回0,失败返回-1。

4 accept()函数

原型:

int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);

描述:

接收请求

参数:

sockfd:服务器的监听socket描述符

addr:请求链接方的地址

addrlen:地址长度

返回值:

成功返回一个新的socket描述符,失败返回-1。


5 收发消息相应函数

read()/write();
recv()/send();
readv()/writev();
recvmsg()/sendmsg();/* 推荐 */
recvfrom()/sendto();

原型:

 #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);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
             const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
             struct sockaddr *src_addr, socklen_t *addrlen);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

描述:

read相应函数可以从socket描述符中读取内容

write相应函数可以把内容写道socket描述符中

参数类型:

sockfd:socket描述符

buf/msg:数据流

len/count:数据长度

flags:调用执行方式,一般设为0

dest_addr:目标地址

src_addr:源地址


返回值:

read相应函数成功时返回实际所读到的字节数,结束返回0,错误返回小于0的数。

write相应函数成功时返回实际所写的字节数,失败返回-1。


6 close函数

原型:

int close(int fd);

描述:

关闭socket

参数:

fd:要关闭的socketfd或者文件fd

返回值:

成功返回0,失败返回-1


7 perror

原型:

void perror(const char *s);

描述:

将上一个函数发生错误的原因输出到stderr,参数s先打印出来,后面加上错误原因字符串,错误字符串依据全局变量errno的值决定的。

在库函数中有个errno变量,每个值对应着以字符串表示的错误原因。当调用某些函数出错时,函数就会重置errno的值。

参数:

错误信息之前的字符串。


8 字节序转换函数

首先有两个概念:

NBO:Network Byte Order 网络字节序,从高到底的顺序从存储(大端优先)。

HBO:Host Byte Order 主机字节序,不同的CPU不同,因此需要转换成NBO。

#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue);/*host to network Short init*/
uint32_t htonl(uint32_t host32bitvalue);/* host to network long init */
uint16_t ntohs(uint16_t net16bitvalue);/*network to host Short init*/
uint32_t ntohl(uint32_t net32bitvalue); /*network to host long init*/  

9 地址转换函数

#include <arpa/inet.h>
int   inet_aton(const char *strptr, struct in_addr *addrptr);/*参数1:<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">字符串IP;参数2:地址结构体中的sin_addr;</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">返回:1——字符串IP有效,0——</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">字符串IP</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">有错*/</span>
char* inet_ntoa(struct in_addr inaddr); /*将一个点分IP转换成字符串*/
in_addr_t inet_addr(const char *strptr);/*将字符串IP转换成网络字节序的IPV4地址*/
#include <netinet/in.h>
#define INET_ADDRSTRLEN  16
#define INET6_ADDRSTRLEN 46
#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);/*返回:1——成功,输入的不是有效表达格式,-1——出错*/
const char* inet_ntop(int family, const void *addrptr, char *strptr, size_t len); /*返回:指向结果的指针——成功,NULL——出错*/

后面一组是比较新的函数,可以处理IPV4和IPV6。


10 setsockopt

原型:

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

描述:

在做服务器端开发的时候,经常会遇到这样的问题:程序第一次能启动,后来就一直报错——端口被占用,导致程序起不了。

原因是在程序绑定的端口在前一次程序退出之后并没有被释放,这就需要使用这个函数来设置socket状态。

参数:

sockfd:socket描述符

level:定义层次,支持SOL_SOCKET(通用套接字)、IPPROTO_TCP(TCP套接字)、IPPROTO_IP(IPV4)和IPPROTO_IPV6((IPV6)

optname:选择名称

optval:选项值,是一个指向变量的指针类型:整形,套接字结构体,其他类型linger{},timeval{}

optlen:选项长度

返回值:

成功返回0,失败返回-1。

optname-选择名称 详解:

选项名称        说明                  数据类型
========================================================================
            SOL_SOCKET
------------------------------------------------------------------------
SO_BROADCAST      允许发送广播数据            int
SO_DEBUG        允许调试                int
SO_DONTROUTE      不查找路由               int
SO_ERROR        获得套接字错误             int
SO_KEEPALIVE      保持连接                int
SO_LINGER        延迟关闭连接              struct linger
SO_OOBINLINE      带外数据放入正常数据流         int
SO_RCVBUF        接收缓冲区大小             int
SO_SNDBUF        发送缓冲区大小             int
SO_RCVLOWAT       接收缓冲区下限             int
SO_SNDLOWAT       发送缓冲区下限             int
SO_RCVTIMEO       接收超时                struct timeval
SO_SNDTIMEO       发送超时                struct timeval
SO_REUSERADDR      允许重用本地地址和端口         int
SO_TYPE         获得套接字类型             int
SO_BSDCOMPAT      与BSD系统兼容              int
========================================================================
            IPPROTO_IP
------------------------------------------------------------------------
IP_HDRINCL       在数据包中包含IP首部          int
IP_OPTINOS       IP首部选项               int
IP_TOS         服务类型
IP_TTL         生存时间                int
========================================================================
            IPPRO_TCP
------------------------------------------------------------------------
TCP_MAXSEG       TCP最大数据段的大小           int
TCP_NODELAY       不使用Nagle算法             int
========================================================================

#对应一个函数:int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);





持续更新....................