C语言网络编程之Socket基础

3/8/2017来源:ASP.NET技巧人气:1595

  操作系统在应用程序与协议栈软件之间提供一个软件接口socket套接口,使我们可以简单、方便地调用TCP/ip协议栈提供的功能。

  套接字应用程序编程接口是网络应用程序利用网络协议栈进行通信时所使用的接口,是应用程序与协议栈软件之间的接口,简称套接字编程接口(Socket API)。它定义了应用程序与协议栈软件进行交互时可以使用的一组操作,决定了应用程序使用协议栈的方式、应用程序所能实现的功能。

Socket套接口

  是对网络中不同主机上应用进程之间进行双向通信的端点的抽象,一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议栈交换数据的机制。

两台主机的socket模式:

套接字在TCP/IP协议中的位置:

从套接字所处的地位来讲:套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议栈进行通信的接口,是应用程序与网络协议栈进行交互的接口。

从实现的角度来讲(内部实现复杂):套接字是一个复杂的软件机制,包含了许多数据结构,由操作系统内核管理。

从使用的角度来讲(对外接口简单):对于套接字的操作形成了一种网络应用程序的编程接口(API)。

总之,套接字是网络通信的基石(应用软件)。

Socket套接口的特点

操作系统对文件和所有其它的输入/输出设备采用一种统一的的操作模式,就是“打开-读-写-关闭”(open-read/write-close)的I/O模式。当TCP/IP协议被集成到操作系统内核中的时候,相当于在操作系统中引入了一种新型的I/O操作。套接字编程接口也可以看作一种输入/输出机制。但是,用户进程与网络协议的交互作用实际要比用户进程与传统的I/O设备相互作用要复杂得多。

基于Socket套接口的通信过程

主机A上的网络应用程序调用发送函数将数据写入自身socket

Socket中的内容通过主机A的网络管理软件和网卡发送到主机B

主机B的网卡接收到数据后,通过网络管理软件将数据送入主机B的socket

主机B的网络应用程序能够在它的socket中读取数据

对于网络应用程序来说,网络通信被层层封装,抽象为写入和读取两个主要功能, 这两个功能是通过socket套接口来实现和完成的

Socket的分类

三种套接口:数据报、流式、原始。每一个套接口都有它确定的类型,只有相同类型的套接字才能相互通信。

数据报套接字(Datagram SOCKET)

数据报套接字提供无连接的不可靠的独立的数据报传输服务。

数据报套接字使用UDP数据报协议形成进程间通信

具有UDP协议为上层所提供的服务的所有特点

流式套接字(Stream SOCKET

流式套接字提供双向的、有序的、无重复的、无信息边界的可靠的数据流传输服务

使用TCP协议形成进程间通信

具有TCP协议为上层所提供的服务的所有特点

在使用流式套接字传输数据之前,必须在数据的发送端和接收端之间建立连接

原始套接字

提供了读写IP/ICMP/IGMP、构造特殊的IP报文的功能。

三种类型的套接口(套接字)

Socket的地址结构

通用地址结构——sockaddr

INET协议族地址结构——sockaddr_in

IPv4地址结构——in_addr

通用地址结构——sockaddr

 
   struct sockaddr {

unsigned short sa_family; // 地址家族

char sa_data; // 协议地址

}

Internet协议族地址结构

 
  sockaddr_in结构 
     struct sockaddr_in {

short sin_family; //地址家族 u_short sin_port; //端口号 struct in_addr sin_addr; //IP 地址 unsigned char sin_zero[8]; //Unused };

in_addr结构,存储32位IP地址。 struct in_addr {

unsigned long s_addr; };

地址家族

The family is one of AF_UNIX Unix internal PRotocols AF_INET Internet protocols AF_NS Xerox NS protocols AF_IMPLINK IMP link layer 其中:AF_ 代表“address family”

三种地址结构的用法

 
 struct sockaddr_in myad; 
 memset(&myad,0,sizeof(struct sockaddr_in)); 
 myad.sin_family=AF_INET; 
 myad.sin_port=htons(8080); 
 myad.sin_addr.s_addr=htonl(INADDR_ANY); 
 //myad.sin_addr.s_addr=inet_addr(“132.241.5.10”);

函数调用时强制转换为sockaddr类型,如:

 
  accept(listenfd,(sockaddr*)(&myad),&addrlen); 
 

几个函数转换

双字节转换short—用于端口格式转换  htons:主机字节序转换成网络字节序  ntohs:网络字节序转换成主机字节序 四字节转换long —用于IP地址格式转换  htonl:主机字节序转换成网络字节序  ntohl:网络字节序转换成主机字节序