socket通讯原理及实现(C语言实现)


在文章的开始我想提出几个问题

  1. 什么是TCP/IP , UDP?
  2. Socket在哪里?
  3. Socket是什么?

什么是TCP/IP , UDP?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
Socket是什么?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
Socket在哪里?
下面这张图说明了Socket存在的位置
在这里插入图片描述在网络编程中 , 要遵循一下这样的流程进行编写
在这里插入图片描述
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

1) socket()函数

int socket(int domain, int type, int protocol);

domain 即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

名称 含义 名称 含义
PF_UNIX,PF_LOCAL 本地通信 PF_X25 ITU-T X25 / ISO-8208协议
AF_INET,PF_INET IPv4 Internet协议 PF_AX25 Amateur radio AX.25
PF_INET6 IPv6 Internet协议 PF_ATMPVC 原始ATM PVC访问
PF_IPX IPX-Novell协议 PF_APPLETALK Appletalk
PF_NETLINK 内核用户界面设备 PF_PACKET 底层包访问

        函数socket()的参数domain用于设置网络通信的域,函数socket()根据这个参数选择通信协议的族。通信协议族在文件sys/socket.h中定义。
type指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
protocol故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议.
注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(addressfamily , AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。

sockaddr_in(在netinet/in.h中定义):
struct sockaddr_in
{
   
   
short sin_family;   /*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/

unsigned short sin_port;   /*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/

struct in_addr sin_addr;  /*IP address in network byte order(Internet address)*/

unsigned char sin_zero[8];  /*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/
};

2) bind()函数

int bind(int sockfd, const struct sockaddr addr, socklen_t addrlen);

正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

函数的三个参数分别为:
sockfd即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
addr一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,
如ipv4对应的是

struct sockaddr_in
 {
   
   
   sa_family_t sin_family;
   in_port_t sin_port;
   struct in_addr sin_addr;
};

struct in_addr 
{
   
   
   uint32_t s_addr;
};

ipv6对应的是

struct sockaddr_in6
 {
   
   
   sa_family_t sin6_family;
   in_port_t sin6_port;
   uint32_t sin6_flowinfo;
   struct in6_addr sin6_addr;
   uint32_t sin6_scope_id;
};

struct in6_addr 
{
   
   
   unsigned char s6_addr[16];
};

Unix域对应的是

#define UNIX_PATH_MAX 108

struct sockaddr_un 
{
   
   
   sa_family_t sun_family;
   char 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值