本文章主要讲解linux网路编程socket通信中常用到的结构体组成和作用

右图为各个结构间的对应关系(图来始于“爱编程的大丙”)

1.结构体sockaddr:

<code class="prism language-c">/************************************
**sa_family : 地址协族议,常用值:AF_INET(网络通讯) / AF_UNIX(linux 本地通讯)
**sa_data : 该数组存储网络端口port,IP地址(网络字节序),多出内存保留
*************************************/
struct sockaddr
{
	unsigned  short  sa_family;     /* address family, AF_xxx:地址族协议 */
	char  sa_data[14];              /* 14 bytes of protocol address:// 端口(2字节) + IP地址(4字节) + 填充(8字节)*/
};

该结构体structsockaddr通常用于以下socket通信api函数

int bind(int sockfd, const struct sockaddr * my_addr, socklen_t addrlen);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int connect(int soctfd, const struct sockaddr * addr, int addrlen);

linux struct sockaddr_in_linux struct sockaddr_in_linux struct sockaddr_in

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

用户通常不会直接使用结构体structsockaddr,一般使用结构体structsockaddr_in或则structsockaddr_un强制转换成structsockaddr类型使用;诸如下边函数使用:

struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);
servaddr.sin_port = htons(8888);
if(connect(socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 )
{
	perror("socket connect failed!");
	return -1;
}

2.结构体structsockaddr_in

linux struct sockaddr_in_linux struct sockaddr_in_linux struct sockaddr_in

typedef unsigned short  	uint16_t;
typedef unsigned int    	uint32_t;
typedef uint16_t 			in_port_t;
typedef uint32_t 			in_addr_t;
typedef unsigned short int  sa_family_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
struct in_addr
{
    in_addr_t s_addr;
};  
// sizeof(struct sockaddr) == sizeof(struct sockaddr_in)
struct sockaddr_in
{
    sa_family_t 	sin_family;			/* 地址族协议: AF_INET*/
    in_port_t 		sin_port;         	/* 端口, 2字节-> 大端(网络字节序)  */
    struct 			in_addr sin_addr;   /* IP地址, 4字节 -> 大端(网络字节序)  */
    unsigned char 	sin_zero[8];		/* 填充 8字节 */
}; 

linux struct sockaddr_in_linux struct sockaddr_in_linux struct sockaddr_in

结构体structsockaddr_in适用于socket网路套接字通信

3.结构体structsockaddr_un

typedef unsigned short int  sa_family_t;
 struct sockaddr_un 
 {
	sa_family_t sun_family; /*地址族协议:PF_UNIX或AF_UNIX */
	char sun_path[108]; 	/* 路径名 */
 };

结构体structsockaddr_un适用于本地进程间通信的UNIX套接字通信。进程间通讯的一种方法是使用UNIX套接字,人们在使用这些方法时常常用的不是网路套接字linux struct sockaddr_indeepin linuxlinux环境变量,而是一种称为本地套接字的形式。这样做可以防止为黑客留下侧门。使用UNIX套接字跟使用网路套接字类似,只需将变量参数structsockaddr_in换成structsockaddr_un输入到响应的socket套接字api函数上即可linux struct sockaddr_in,如下所示:

/****************************** socket 网络套接字通讯 ******************************/
struct sockaddr_in server;
int listenfd
socklen_t len;
if( (socketfd = socket(AF_INET, SOCK_STREAM, 0) ) ==  -1)	//socket函数类似于open函数,打开并创建一个socket,AF_INET使用IPV4协议族,SOCK_STREAM为TCP套接口

linux struct sockaddr_in_linux struct sockaddr_in_linux struct sockaddr_in

{ perror("socket create failed!"); return -1; } memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; //IPV4协议 server.sin_port = htons(8888); //端口号 server.sin_addr.s_addr = htonl(INADDR_ANY); //自动生成自身IP做服务器IP给客户端连接 len = sizeof(struct sockaddr); if(bind(listenfd, (struct sockaddr *)&server, len)<0) //绑定 { perror("bind error."); return -1; } ........ /*省略后续socket api函数配置*/ /****************************** socket UNIX套接字通讯 ******************************/

linux struct sockaddr_in_linux struct sockaddr_in_linux struct sockaddr_in

struct sockaddr_un server; int listenfd; if( (listenfd = socket(AF_UNIX, SOCK_STREAM, 0) ) == -1) //进程间socket UNIX套接字通讯 { perror("socket create failed!"); return -1; } memset((void*)&server,0,sizeof(struct sockaddr_un)); server.sun_family = AF_UNIX; strcpy(server.sun_path, "/tmp/testsocketUNIX"); unlink(server.sun_path); if(bind(listenfd, (struct sockaddr*)&server, sizeof(server)) < 0) { perror("fail to bind"); return NULL; } ........ /*省略后续socket api函数配置*/

Tagged:
Author

这篇优质的内容由TA贡献而来

刘遄

《Linux就该这么学》书籍作者,RHCA认证架构师,教育学(计算机专业硕士)。

发表回复