关于socket的几个问题

主要说的是几个转换函数

  • 网络字节与本地字节的相互转化
  • 二进制ip与十进制ip的转换
  • ip地址与主机名的转化

1.socket类型

socket:linux中的网络编程是用socket接口进行的,socket是一种特殊的I/O接口,也是一种文件描述符,socket是一种常用的进程间通信机制,通过他不仅可以实现本机上的进程   

              间的通信,还可以实现不同机器上的进程间的通信,可以通过网络实现不同机器上的不同机器上的进程进行通信

每一个socket都用一个半相关描述{协议,本地地址,本地端口}来表示,一个完整的套接字用一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}来表示,socket也有类似于打开文件的操作,然后就可以通过这个socket建立连接,数据传输等操作。

2.socket类型

(1)流式socket(SOCKET_STREAM)

    流式套接字提供可靠的,面向连接的通信流,使用TCP协议,保证了数据传输的正确性和顺序性

(2)数据报socket(SOCKET_DGRAM)

     定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,不保证是可靠的,无差错的,使用协议UDP

(3)原始socket

    原始套接字允许对底层协议如IP/ICMP进行直接访问,他功能强大但使用不方便,主要用于一些协议的开发

3.两种数据结构的介绍

  两种重要的数据结构:socketaddr和socketaddr_in这两种数据结构都是用来保存socket信息的

struct sockeaddr
{
	unsigned short sa_family ;/*地址族*/
	char sa_data[14] ;/*14字节的协议地址,包含该socket的ip地址和端口号*/
};

struct sockeaddr_in
{
	short sa_family ;/*地址族*/
	unsigned short int sin_port ;/*端口号*/
	struct in_addr sin_addr ;/*ip地址*/
	unsigned char sin_zero[8] ;/*填充为0为了保持struct socketaddr同样的大小*/
};

这两种结构是可以相互转化的,socketaddr_in使用更加方便,在建立socketaddr或socketaddr_in,就可以对socket进行适当操作了。

结构中的sa_family可选的常见值如下:

4.数据存储的优先顺序

计算机中数据存储有两种方式:高位字节优先(大端模式),地位字节优先(小端模式,PC机通常采用小端模式),记得有次面试问我这个,我完全不知道什么东西,在那乱说,结果可想而知,但internet使用的是高位字节优先的模式,所以需要这两种模式进行转换,主要有四个函数:htons(),ntohs(),htonl(),ntohl(),四个函数分别实现网络地址和机器地址的转换,这个是很好记忆的,h代表host,n代表networks,s是short代表ip端口号,l是long代表ip地址。

下面列出了这几个函数的语法格式:

ps:这些函数只是使其得到相应的字节序,用户不需知道真的需要转换,如果不需要转换,这些系统的函数将会定义成空宏

5.地址格式转换

用户在表达地址时使用点分的进制,或者冒号分开的ipv6地址,而在socket编程中使用的是二进制的ip地址,这就需要将这两个值进行转换,ipv4中使用的函数是inet_aton(),

inet_addr(),inet_ntoa(),ipv4和ipv6兼容的函数有inet_pton(),inet_ntop().

inet_pton()------------将点分的十进制映射成二进制地址

inet_ntop()------------将二进制的地址映射成点分的十进制的地址

inet_pton()函数语法的格式:

inet_ntop()函数语法格式:

6.名字地址转换

ip地址很长,特别到了ipv6的时候就更难记住了,那我们可以使用主机名是很好的选择,linux中有一些函数可以实现主机和ip的转换,这些常见的函数如下:

gethostbyname(),gethostbyaddr(),getaddrinfo()

gethostbyname()----------将主机名转换成ip

gethostbyaddr()---------------将主机名转换成地址

getaddrinfo()---------------能够自动识别ipv4和ipv6地址

gethostbyname()和gethostbyaddr()都涉及到了一个hostent结构体,他的形式是这样的:

struct hostent
{
	char *h_name ;/*正式主机名*/
	char ** h_aliases ;/*主机别名*/
	int h_addrtype ;/*地址类型*/
	int h_length ;/*地址字节长度*/
	char **h_addr_list ;/*指向ipv4或ipv6的地址指针数组*/	
};

调用gethostbyname()或者gethostbyaddr()能够返回hostent结构体的相关信息

getaddrinfo()涉及到一个结构体addrinfo结构体

struct addrinfo
{
	int ai_flags ;/*AI_PASSIVE,AI_CANONNAME*/
	int  ai_family ;/*主机别名*/
	int ai_socketype ;/*地址类型*/
	int ai_protocol ;/*协议类型*/
	int ai_addrlen ;/*地址字节长度*/
	char *ai_canonname ;/*主机名*/
	struct socketaddr *ai_addr ;/*socket结构体*/
	struct addrinfo *ai_next ; /*下一个指针链表*/	
};

与hostent相比,addrinfo结构体包含了更多的信息.

gethostbyname()函数语法如下:

ps:调用函数时首先对hostent结构体中的h_addrtype,h_lenth进行设置,如果IPV4则可以设置成AF_INET和4,若为IPV6则可以设置成AF_INET6和16,如果不设置则默认为ipv4类型

getaddrinfo函数语法如下:



ps:在调用之前可以对hints服务线索进行设置,这里涉及到addiinfo结构体,他的常用选项如下所示:

ps:(1)服务器在调用getaddrinfo(),ai_flags通常设置成AI_PASSIVE,用于bind()函数,主机名通常设置成NULL

        (2)客户端在调用getaddinfo时,ai_flags一般不设置成AI_PASSIVE,但主机名nodename和服务器名一般不为空

        (3)即使不设置ai_flags为AI_PASSIVE,取出的地址也可以绑定,取出的地址也是应该可以绑定的,很多程序的ai_flags直接设置成0,即三个标志位都不设置,这种情况下只  要hostname和servname设置的没有问题也是可以正常绑定的

下面有个关于getaddrinfo的使用例子

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main()
{
    struct addrinfo hints, *res = NULL ;
    int rc ;
    memset (&hints, 0, sizeof(hints)) ;
    /*初始化hints结构体*/
    hints.ai_flags = AI_CANONNAME ;//返回主机名称
    hints.ai_family = AF_UNSPEC ;
    hints.ai_socktype = SOCK_DGRAM ;
    hints.ai_protocol = IPPROTO_UDP ;
    rc = getaddrinfo("localhost", NULL, &hints, &res) ;
    if (rc != 0)
    {
        perror("getaddrinfo") ;
        exit(1) ;
    }else
    {
        printf("host name is %s\n", res->ai_canonname) ;
    }
    exit(0) ;
}
这段程序的运行结果如下:

由此就可以得出主机名称。


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值