Socket函数深入学习

本文深入介绍了Socket编程中的关键结构体、字节转换函数以及核心的网络通信函数,包括socket(), connect(), bind(), listen(), accept(), send(), recv()等。通过这些函数,开发者可以实现网络通讯并对IP/TCP层协议进行控制。" 105831574,8388287,VB中使用Crypt32.dll进行Base64加密解密,"['加密算法', 'VB编程', '数据编码']
摘要由CSDN通过智能技术生成

1. 概述

          在网络协议中,分层思想是非常重要的,各层协议分工明确,各干各事。在现实世界中,IP网际层的实现分布在路由器和各种PC终端中,TCP传输层的实现则存在于PC终端。换句话说,路由器只实现IP协议,而终端PC的操作系统同时实现了IP和TCP层协议。为了让开发者实现各种应用程序,不同的操作系统都会提供了一组socket函数,供开发者使用。通过socket函数,开发者能够进行网络通讯,并且能够对IP/TCP层协议的某些特性进行控制。

          在所有的套接字函数中,Berkeley套接字(也称为BSD套接字)使用的最为广泛。由于专利原因,Berkeley套接字由C语言实现,只被使用在UNIX操作系统上。但其接口形式成为了事实上的网络套接字的标准,不同操作系统都有类似接口,包括Linux和Window;大多数其他的编程语言也使用了与Berkeley套接字类似的接口。

          Berkeley套接字API库提供的函数包括:
          1.  socket()  创建一个新的确定类型的套接字,类型用一个整型数值标识(文件描述符),并为它分配系统资源。
          2.  bind()  一般用于服务器端,将一个套接字与一个套接字地址结构相关联。
          3.  listen()  用于服务器端,使一个绑定的TCP套接字进入监听状态。
          4.  connect()  用于客户端,为一个套接字分配一个自由的本地端口号。 如果是TCP套接字的话,它会试图获得一个新的TCP连接。
          5.  accept()  用于服务器端。 它接受一个从远端客户端发出的创建一个新的TCP连接的接入请求,创建一个新的套接字,与该连接相应的套接字地址相关联。
          6.  send() recv() ,或者 write() read() ,或者 recvfrom() sendto() , 用于往/从远程套接字发送和接受数据。
          7.  close()  用于系统释放分配给一个套接字的资源。 如果是TCP,连接会被中断。
          8.  shutdown()  用于关闭socket连接。该函数允许只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。
          9.  gethostbyname() gethostbyaddr()  用于解析主机名和地址。
          10.  select()  用于修整有如下情况的套接字列表: 准备读,准备写或者是有错误。
          11.  poll()  用于检查套接字的状态。 套接字可以被测试,看是否可以写入、读取或是有错误。
          12.  getsockopt()  用于查询指定的套接字一个特定的套接字选项的当前值。
          13.  setsockopt()  用于为指定的套接字设定一个特定的套接字选项。
          14.  htons() htonl() ntohs() ntohl()  用于网络序和本机序转换。
          15.  inet_addr()  用于字符串形式的IP地址和网络序形式的IP地址的转换。
          16.  inet_ntoa()  用于网络序形式的IP地址和字符串形式的IP地址的转换。


2. 结构体和函数

2.1 结构体

          套接字用到的各种数据类型
          1. socket描述符。它是一个int值。在window下可能被定义为SOCKET,SOCKET也是一个int值,根据平台不同,被定义为int32或者int64。
[cpp]  view plain copy
  1. struct sockaddr {   
  2.    unsigned short sa_family; /* 地址家族, AF_xxx */   
  3.    char sa_data[14]; /*14字节协议地址*/   
  4. };   

          这个结构被为许多类型的套接字储存套接字地址信息。sa_family一般为"AF_INET",sa_data包含套接字中的目标地址和端口信息。在一个字符数组中同时存储目标地址和端口信息非常令人困惑,所以还存在一个并列的结构,struct sockaddr_in ("in" 代表 "Internet"。),其定义如下:
[cpp]  view plain copy
  1. #include <netinet/in.h>  
  2. struct sockaddr_in {   
  3.    short int sin_family; /* 通信类型 */   
  4.    unsigned short int sin_port; /* 端口 */   
  5.    struct in_addr sin_addr; /* Internet 地址 */   
  6.    unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/   
  7. };   


          可以看到其中sin_zero 被加入到这个结构,目的是为了使sockaddr_in和 struct sockaddr 长度一致,可以使用函数 bzero() 或 memset() 来全部置零。 而 sin_family 和 struct sockaddr 中的 sa_family 一致,能够设置为 "AF_INET"。结构体 sin_port和 sin_addr 则是网络字节顺序 (Network Byte Order)。(关于网络序可见文章数据类型转换)

          struct in_addr的定义如下:
[cpp]  view plain copy
  1. #include <netinet/in.h>  
  2. struct in_addr {   
  3.    unsigned long s_addr;   
  4. };   


2.2 字节转换:

[cpp]  view plain copy
  1. htons()--"Host to Network Short"  
  2. htonl()--"Host to Network Long"  
  3. ntohs()--"Network to Host Short"  
  4. ntohl()--"Network to Host Long"  

          其中 short (两个字节)和 long (四个字节)。这些函数对于变量类型 unsigned 也是适用对。假设想将 short 从本机字节顺序转换为网络字节顺序。可以用 "h" 表示 "本机 (host)",接着是 "to",然后用 "n" 表示 "网络 (network)",最后用 "s" 表示 "short": h-to-n-s, 或者 htons() ("Host to Network Short")。


2.3 IP 地址和字符串转化:

          inet_addr()和inet_ntoa() 用于字符串和int值之间的字符串转换。使用如下:
[cpp]  view plain copy
  1. sockaddr_in ina;  
  2. ina.sin_addr.s_addr = inet_addr("192.168.1.1");  
  3.   
  4. char *a1;  
  5. a1 = inet_ntoa(ina.sin_addr); /* 这是192.168.1.1*/  
  6. printf("address 1: %s/n",a1);  


2.4 函数:

2.4.1 socket()函数

[cpp]  view plain copy
  1. #include <sys/types.h>;   
  2. #include <sys/socket.h>;   
  3. int socket(int domain, int type, int protocol);   

           参数 domain:  通常被设置成 "AF_INET"。
           参数 type:  告诉内核是 SOCK_STREAM 类型还是 SOCK_DGRAM 类型。
           参数 protocol : 通常被设置为 "0"。
          如果需要更多的信息,可以看 socket() 的 man帮助。
           返回值:  socket() 只是返回你以后在系统调用种可能用到的 socket 描述符,在错误的时候返回-1。全局变量 errno 中将储存返回的错误值。

2.4.2 connect()函数

[cpp]  view plain copy
  1. #include <sys/types.h>;   
  2. #include <sys/socket.h>;  
  3. int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);   

          参数 sockfd  :是系统调用 socket() 返回的套接字文件描述符。
          参数 serv_addr : 是 保存着目的地端口和 IP 地址的数据结构 struct sockaddr。
          参数 addrlen:  设置 为 sizeof(struct sockaddr)。
          connect() 函数只用于客户端,使socket变成主动socket (active socket)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值