Linux网络学习_socket套接字

Posted Leslie X徐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux网络学习_socket套接字相关的知识,希望对你有一定的参考价值。

套接字

  1. 概念
  • Socket(套接字)是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段。
  • Linux中的网络编程通过Socket接口实现,Socket即是一种特殊的IO,提供对应的文件描述符。
  • 一个完整的Socket都有一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}(五元组);
  • 每一个Socket有一个本地的唯一Socket,由操作系统分配。
  1. 创建Socket
#include <sys/types.h>  
#include <sys/socket.h>
int socket(int domain, int type, int protocol)

  • 返回:成功返回描述符,出错返回-1
  • Socket创建在内核中,若创建成功则返回内核文件描述表中的socket描述符。
    参数:
    • domain
      • AF_INET:IPv4因特网域
      • AF_INET6:IPv6因特网域
      • AF_UNIX:unix域
      • AF_UNSPEC:未指定
    • type
      • SOCK_STREAM:
        • 流式的套接字可以提供可靠的、面向连接的通讯流。他使用了TCP协议。TCP保证了数据传输的正确性和顺序性。
      • SOCK_DGRAM:
        • 数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。使用数据报协议UDP协议
      • SOCK_RAW:
        • 原始套接字允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实现的测试等。
      • SOCK_SEQPACKET:
        • 长度固定、有序、可靠的面向链接报文传递。
    • protocol
      • 通常为0,表示按给定的域和套接字类型选择默认协议
  1. 字节序
  • 不同体系结构的主机使用不同的字节序存储器来保存多字节整数。字节存储顺序不同,有的系统是高位在前,低位在后(大端字节序),而有的系统是低位在前,高位在后(小端字节序)。
  • 字节序分为大端 字节序(big-endiane)和小端字节序(little-endian)。
  • 网络协议使用网络字节序即大端字节序。
  1. 字节序转换函数
  • 网络传输的所有数据是一定要统一顺序的(网络字节序)。所以对于内部字节表示顺序和网络字节顺序不同的机器,就一定要对数据进行转换:
    • h–host主机,n–net网络,l–long,s–short
    • uint32_t htonl(uint32_t hostlong);
      • 将一个32位整数由主机字节序转换成网络字节序
    • uint16_htons(uint16_t hostshort);
      • 将一个16位整数由主机字节序转换成网络字节序
    • uint32_t ntohl(uint32_t netlong);
      • 将一个32位整数由网络字节序转换成主机字节序
    • uint16_t ntohs(uint16_t netshort);
      • 将一个16位整数由网络字节序转换成主机字节序
  1. 通用地址结构
#include <sys/socket.h>
struct sockaddr{

	unsigned short sa_family;	/*Internet地址族,AF_xxx*/
	char sa_data[14];	/*14 bytes的协议地址*/
};

  • sa_data 包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂融在一起的。
  • sa_family 一般来说,IPv4使用AF_INET。
  • 在传递给需要地址结构的函数时,把指向该结构的指针转换成(struct sockaddr*)传递进去。
  1. 因特网地址结构
struct in_addr{
	in_addr_t		s_addr; /*ipv4地址*/
};

struct sockaddr_in{
	short int 	sin_family; 	//Internet地址族如AF_INET(主机字节序)
	unsigned short int 	sin_port; //端口号,16位值(网络字节序)
	struct in_addr	sin_addr; //Internet地址,32位IPv4地址(网络字节序)
	unsigned char	sin_zero[8]; //添0(为了格式对齐的填充位)
};

因特网地址结构(sockaddr_in)和通用地址结构(sockaddr)类型是等效的,可以互相转换,通常使用sockaddr_in更为方便。

  1. IPv4地址族和字符地址间的转换
    (1)网络字节序转换成点分十进制:
#include <arpa/inet.h>
const char* inet_ntop(
								int domain, 
								const void* restrict addr,
								char* restrict str,
								socklen_t size );
								
  • 返回:成功返回地址字符串指针,出错返回NULL

(2)点分十进制转换为网络字节序

#include <arpa/inet.h>
int inet_pton(
					int domain,
					const char* restrict str,
					void* restrict addr);
  • 返回:成功返回1,无效格式返回0,出错返回-1
  • 参数
    • domain:Internet地址族,如AF_INET
    • addr:Internet地址,32位IPv4地址(网络字节序)
    • str:地址字符串(点分十进制)指针
    • size:地址字符串大小
  1. 填写IPv4地址族结构案例
struct sockaddr_in sin; //定义一个aockaddr_in结构体
char buf[16];
memset(&sin,0,sizeof(sin)); //内存清0
sin.sin_family = AF_INET; //填写Internet地址族
sin.sin_port = htons((short)3001); //填写端口号(网络字节序)

//填充sin_addr
if(inet_pton(AF_INET,"192.168.2.1",&sin.sin_addr.s_addr)<=0)
{
	//错误处理
}
printf("%s\\n",inet_ntop(AF_INET,
									&sin.sin_addr.s_addr,
									buf,
									sizeof(buf)));

以上是关于Linux网络学习_socket套接字的主要内容,如果未能解决你的问题,请参考以下文章

Linux学习_网络广播

Linux系统开发: 学习Linux下网络编程

Linux下socket编程基本知识

Linux学习_UDP编程

Python学习之旅 —— socket篇

Python学习 : Socket编程