套接字学习总结

不同计算机上运行的进程间的通信机制:网络进程间通信

 
套接字:
(1)创建一个套接字
#include <sys/socket.h>
 
int      socket ( int domain  ,  int   type  , int   protocol);
参数说明:
domain:确定通信的特性,包括地址格式。通常以AF_开头,也指地址族。其中:
AF_INET:IPv4因特网域
type:确定套接字类型。其中比较重要的有:SOCK_STREAM   有序、可靠、双向的面向连接字节流
protocol:通常是0
在AF_INET通信域中套接字类型SOCK_STREAM的默认协议时TCP,传输控制协议
 
(2)关闭套接字
可以使用close函数,但是使用shutdown函数更好一些。其定义如下:
int   shutdown(  int sockfd  ,  int  how);
参数说明:
how:SHUT_RD(关闭读端),那么将无法从套接字读取数据;
         SHUT_WR(关闭写端),SHUT_RDWR(读写端均关闭)
不适用close是因为,close直到最后一个该文件描述符引用结束以后,才会释放相关的系统资源。而shutdown可以直接使一个套接字处于不活动的状态。而且使用shutdown也使得我们在关闭单独的一个端口(读或者写)比较方便。
 
进程的标识有两个部分:
计算机的网络地址可以帮助标识网络上想与之通信的计算机,而服务可以帮助标识计算机上特定的进程。
 
字节序:
字节序是一个处理器架构的特性,用于指示像整数这样的大数据类型的内部字节的顺序。
如果处理器架构支持大端字节序,那么最大字节地址对应于数字的最低有效字节(LSB);
小端字节序则相反:数字最低字节对应于最小字节地址
注意点:不管字节如何排序,数字最高为总是在左边,最低位总是在右边。
 
TCP/IP协议栈采用大端字节序,所以应用程序在处理器的字节序和网络字节序之间进行转换。
对于TCP/IP应用程序,提供了四个通用函数以实施在处理器字节序和网络字节序之间的转换:
 
#include <arpa/inet.h>
uint32_t   htonl ( uint32_t    hostint32);
该函数返回值:以网络数据字节序表示的32位整型数
 
uint16_t   htons( uint16_t   hostint16);
返回值:以网络数据字节序表示的16位整型数
 
uint32_t   ntohl ( uint32_t  netint32);
返回值:以主机字节序表示的32位整型数
unint16_t  ntohs( uint16_t   netint16)
 
记忆规则:h表示主机(host)字节序,n表示网络(net)字节序。l 表示长(long)整数,s表示短(short)整数。
 
地址格式:
为了使不同格式地址能够被传入到套接字函数中,地址呗强制转换成通用的地质结构sockaddr表示。
struct   sockaddr {
     sa_family_t   sa_family ;
     char             sa_data[];
     ...
};
 
在IPv4因特网域中(AF_INET)中,套接字地址用如下结构sockaddr_in表示:
struct   in_addr{
     in_addr_t      s_addr;    /*ipv4  address*/
};
 
struct   sockaddr_in
{
     sa_family_t     sin_family;//address family
     in_port_t         sin_port; // port   number
     struct   in_addr   sin_addr; // ipv4   address
};
 
有时候需要打印出人能够理解的地址格式。此时需要在二进制地址格式与点分十进制字符串表示的地址之间进行转换。如下:
#include<arpa/inet.h>
 
const   char*  inet_ntop( int domain  ,const  void *restrict  addr,  char *restrict  str,  socklen_t  size);
返回值:成功则返回地址字符串指针
 
int   inet_pton( int  domain,  const char* restrict str , void *restrict addr);
返回值:成功返回1
 

将套接字与地址绑定
int   bind( int  sockkfd , const  struct  sockaddr  *addr , socklen_t   len);
成功返回0,否则,返回-1;
端口号必须不小于1024,除非该进程具有相应的特权。因为端口号小于1024的端口均留作系统特殊功能端口。
对于因特网,如果指定的IP地址为INADDR_ANY,套接字端点可以被绑定到所有的系统网络接口。
 
可以调用函数getsockname()来发现绑定到一个套接字的地址:
int  getsockname( int   sockfd, struct  sockaddr  *restrict  addr,  socklen_t   *restrict  alenp);
其中alenp会被置为地址的大小。
 
如果套接字已经和对方连接,可以调用getpeername来找到对方的地址:
int  getpeername( int   sockfd, struct  sockaddr  *restrict  addr,  socklen_t   *restrict  alenp )
 
 
连接
如果处理的是面向连接的网络服务(SOCK_STREAM, SOCK_SEQPACKET),在开始交换之前,需要在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务器)之间建立一个连接。
 
int  connect  ( int  sockfd , const  struct  sockaddr *addr , socklen_t   len);
 
宣告可以接收连接请求:
int   listen ( int  sockfd,  int  backlog);
参数说明:
backlog:提供一个提示,用于表示该进程所要进入队的连接请求数量。
 
使用accept()函数获得连接请求并建立连接
int   accept ( int  sockfd , struct  sockaddr *restrict  addr , socklen_t  *restrict  len);
成功则返回套接字描述符
 
 
数据传输
虽然可以通过read和write函数进行数据的传输,但是如果想指定选项、从多个客户端接收数据包或者发送带外数据,需要采用专门的函数:
发送数据:
(1)send
ssize_t   send ( int  sockfd,  const  void *buf  ,size_t  nbytes,  int  flags);
send函数和write函数很相似,但是其多支持了第四个参数-flags,其定义如下:
MSG_DONTROUTE:勿将数据路由出本地网络
MSG_DONTWAIT:允许非阻塞操作
MSG_EOR:如果协议支持,此为结束记录
MSG_OOB:....................,发送带外数据
 
(2)sendto
sendto允许在无连接的套接字上指定一个目标地址
ssize_t    sendto ( int  sockfd,  const  void *buf  ,size_t  nbytes,  int  flags,
                         const struct  sockaddr *destaddr, socklen_t  destlen)
 
(3)sendmsg
ssize_t  sendmsg( int  sockfd , const struct   msghdr *msg ,int flags)
 
接收数据:
(1)recv
ssize_t   recv (  int  sockfd,  const  void *buf  ,size_t  nbytes,  int  flags)
 
(2)recvfrom
ssize_t   recvfrom( int  sockfd,  const  void *buf  ,size_t  nbytes,  int  flags,
                         const struct  sockaddr *destaddr, socklen_t  destlen)
 
(3)recvmsg
类似于sendmsg函数的参数
 
 
 (更新中..........)
原文地址:https://www.cnblogs.com/xingma0910/p/3578724.html