[1]Socket简介:
Linux中的网络编程通过Socket(套接字)接口实现,Socket是一种文件描述符。
套接字socket有三种类型:
- 流式套接字(SOCK_STREAM):流式的套接字使用TCP协议,可以提供可靠的、面向连接的通讯流。
- 数据报套接字(SOCK_DGRAM):数据报套接字使用UDP协议定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。
- 原始套接字(SOCK_RAW):原始套接字允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议的测试等。
[2]网络地址:
sockaddr:
Linux中的网络地址有sockaddr结构体指定:
#include <netinet/in.h>
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
//sa_family是地址家族,一般都是“AF_xxx”的形式,IPV4的值为AF_INET。
//sa_data是14字节协议地址。
sockaddr_in:
sockaddr结构体等价于sockaddr_in结构体:
#include <netinet/in.h>
struct sockaddr_in
{
short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP地址 */
unsigned char sin_zero[8]; /* 填0 */
}
struct in_addr
{
unsigned long s_addr;
}
//s_addr: 32位的地址(IP)。
地址转换函数:
字符串IP地址转换为struct in_addr:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *string, struct in_addr *addr);
- 输入参数string包含ASCII表示的IP地址。
- 输出参数addr是将要用新的IP地址更新的结构。
- 返回值:如果这个函数成功,函数的返回值非零。如果输入地址不正确则会返回零。
sruct in_addr转换为字符串IP地址:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
主机名与IP地址:
#include <netdb.h>
#include <sys/socket.h>
struct hostent *gethostbyname(const char *name);
//name:域名或者主机名
//返回值:目标主机的信息(如果函数调用错误,返回值是NULL)
struct hostent {
char *h_name;//主机的规范名
char **h_aliases;//主机的别名
int h_addrtype;//主机ip地址的类型,IPV4(AF_INET)
int h_length;//IP地址的个数
char **h_addr_list;//IP地址列表
};
#define h_addr h_addr_list[0] /* 主机的第一个IP地址*/
[3]字节序转换:
待续
[4]Socket常用函数:
socket
socket()系统调用创建一个套接字并返回一个描述符,该描述符可以用来访问该套接字。
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- domain协议族:常用的协议族有:AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等。
- type套接字类型:常用的类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。
- protocol协议类型:常用的协议有IPPROTO_TCP、IPPTOTO_UDP等。
- 返回值:socket套接字。
bind
bind()函数将socket与本机的特定地址相关联(绑定)。
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- sockfd:socket文件描述符。
- addr:由IP地址和端口号组成的网络终结点地址。
- addrlen:addr的长度。
- 返回值:bind在调用成功时返回0,失败是返回-1。
listen
宣告该套接字可接受连接,并建立一个队列来保存未处理的请求。
#include <sys/socket.h>
int listen(int socket, int backlog);
- backlog:设置队列中可以容纳的未处理连接的最大个数,backlog常用值为5。
- 返回值:成功时返回0,失败时返回-1。
accept
服务器程序创建并绑定了socket之后,就可以通过用accept()来等待客户建立对该socket的连接。
#include <sys/socket.h>
int accept(int socket, struct sockaddr *address, size_t *address_len);
accept()只有当有客户程序尝试连接到由socket参数指定的socket上时才返回。accept()将创建一个新socket来与该客户进行通信,将该socket描述符作为返回值。之后的读写动作都关联到该socket描述符上。参数socket所关联的套接字必须首先已经被bind绑定,而且有listen为其分配连接队列。参数address表示客户的地址,如果不关心客户的地址值可设为空指针。
- socket:侦听套接字的文件描述符。
- address:远程客户程序的网络终结点。
- address_len:address缓冲区的长度。
- 返回值:成功客户程序对应的套接字,失败返回-1。
connect
客户程序连接到服务器监听套接字的函数。
#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address, size_t address_len);
- socket:指定本地的套接字。
- address:远程服务器程序的网络终结点。
- address_len:address缓冲区的长度。
- 返回值:成功返回0,失败返回-1。
如果连接不能立刻建立,connect将阻塞到超时时间,超过超时时间连接将被放弃,连接失败。
close
可以通过close()来终止服务器与客户端的socket连接。
#include <unistd.h>
int close(int socket);
write&read
可以像读写文件一样使用write()和read()函数收发套接字数据。
send
send()同样可以发送数据,与write()不同的是,send()只能用于socket数据的发送。
#include <sys/socket.h>
int send(int socket, const void *buff, int len, int flags)
- socket:套接字文件描述符。
- buff:要发送的数据。
- len:要发送的数据长度。
- flags:一般为0。
- 返回值:成功返回发送的字节数,失败返回-1。
recv
与send()相同,recv()也只能用于socket的数据发送。
#include <sys/socket.h>
int recv(int socket, void *buf, int len, unsigned int flags)
- socket:套接字文件描述符。
- buff:接收数据的缓冲区。
- len:接收数据的缓冲区的长度。
- flags:一般为0。
- 返回值:成功返回接收到的字节数,失败返回-1。
sendto
sendto需要带上发送目的地的地址信息,可以用于UDP通讯的实现,TCP中也可以使用sendto()。
#include <sys/socket.h>
int sendto(int socket, const void *buff, int len, unsigned int flags, const struct sockaddr *addr_to, int addr_len)
- socket:套接字文件描述符。
- buff:待发送数据。
- len:待发送数据的长度。
- flags:一般为0。
- addr_to:目的网络终结点地址。
- addr _len:地址信息的长度。
- 返回值:成功返回已发送的字节数,失败返回-1。
recvfrom
recvfrom()与sendto配套使用,实现数据的收发。
#include <sys/socket.h>
int recvfrom(int socket, const void *buff, int len, unsigned int flags, const struct sockaddr *addr_from, int addr_len);
- socket:套接字文件描述符。
- buff:接收数据的缓冲区。
- len:接收数据的缓冲区的长度。
- flags:一般为0。
- addr_from:缓冲区用于接收远程主机的网络终结点地址。
- addr_len:addr_from缓冲区的长度。
- 返回值:成功返回接收到的字节数,失败返回-1。