【Linux网络编程】套接字简介
00. 目录
文章目录
01. 概述
Socket套接字由远景研究规划局(Advanced Research Projects Agency, ARPA)资助加里福尼亚大学伯克利分校的一个研究组研发。其目的是将TCP/IP协议相关软件移植到UNIX类系统中。设计者开发了一个接口,以便应用程序能简单地调用该接口通信。这个接口不断完善,最终形成了Socket套接字。Linux系统采用了Socket套接字,因此,Socket接口就被广泛使用,到现在已经成为事实上的标准。与套接字相关的函数被包含在头文件sys/socket.h中。
Socket的英文原意是"插座",作为类UNIX系统的进程通信机制,它如同插座一样方便的帮助计算机接入互联网通信。
任何用户在通信之前,首先要先申请一个Socket号,Socket号相当于自己的电话号码。同时要知道对方的电话号码,相当于对方有一个Socket。然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,还要拨对方区号,相当于给出网络地址)。对方假如在场并空闲(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是向电话机发出信号和从电话机接受信号的过程,相当于Socket发送数据和从Socket接受数据。通话结束后,一方挂起电话机,相当于关闭Socket,撤销连接。
由此可见,Socket的通信机制与电话交换机制非常相似。Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。每一个Socket都用一个半相关描述。
一个完整的Socket则用一个相关描述:{协议,本地地址,本地端口}。
02. 套接字属性
套接字的特性有三个属性确定,它们是:域(domain),类型(type),和协议(protocol)。
套接字的域
域指定套接字通信中使用的网络介质。最常见的套接字域是 AF_INET,它是指 Internet 网络,许多 Linux 局域网使用的都是该网络,当然,因特网自身用的也是它。
套接字类型
流套接字(SOCK_STREAM):
流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission Control Protocol)协议。
数据报套接字(SOCK_DGRAM):
数据报套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
原始套接字(SOCK_RAW):
原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送数据必须使用原始套接字。
套接字协议(协议类别)
只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常使用默认即可(也就是最后一个参数填“0”)。
03. socket函数
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); 功能: 创建一个用于网络通信的 socket 套接字(描述符) 参数: family:协议族(AF_UNIX、AF_INET、AF_INET6、PF_PACKET等) type:套接字类型(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW等) protocol:协议类别(0、IPPROTO_TCP、IPPROTO_UDP等),设为 0 表示使用默认协议。 返回值: 成功:套接字 失败(<0)
最常见的套接字域是 AF_UNIX 和 AF_INET,前者用于通过 Unix 和 Linux 文件系统实现的本地套接字,后者用于 Unix 网络套接字。AF_INET 套接字可以用于通过包括因特网在内的 TCP/IP 网络进行通信的程序。微软 Windows 系统的 winsock 接口也提供了对这个套接字域的访问功能。
/* * Address families. */ #define AF_UNSPEC 0 /* unspecified */ #define AF_UNIX 1 /* local to host (pipes, portals) */ #define AF_INET 2 /* internetwork: UDP, TCP, etc. */ #define AF_IMPLINK 3 /* arpanet imp addresses */ #define AF_PUP 4 /* pup protocols: e.g. BSP */ #define AF_CHAOS 5 /* mit CHAOS protocols */ #define AF_IPX 6 /* IPX and SPX */ #define AF_NS 6 /* XEROX NS protocols */ #define AF_ISO 7 /* ISO protocols */ #define AF_OSI AF_ISO /* OSI is ISO */ #define AF_ECMA 8 /* european computer manufacturers */ #define AF_DATAKIT 9 /* datakit protocols */ #define AF_CCITT 10 /* CCITT protocols, X.25 etc */ #define AF_SNA 11 /* IBM SNA */ #define AF_DECnet 12 /* DECnet */ #define AF_DLI 13 /* Direct data link interface */ #define AF_LAT 14 /* LAT */ #define AF_HYLINK 15 /* NSC Hyperchannel */ #define AF_APPLETALK 16 /* AppleTalk */ #define AF_NETBIOS 17 /* NetBios-style addresses */ #define AF_VOICEVIEW 18 /* VoiceView */ #define AF_FIREFOX 19 /* FireFox */ #define AF_UNKNOWN1 20 /* Somebody is using this! */ #define AF_BAN 21 /* Banyan */ #define AF_MAX 22
套接字类型
/* * Types */ #define SOCK_STREAM 1 /* stream socket */ #define SOCK_DGRAM 2 /* datagram socket */ #define SOCK_RAW 3 /* raw-protocol interface */ #define SOCK_RDM 4 /* reliably-delivered message */ #define SOCK_SEQPACKET 5 /* sequenced packet stream */
参考示例:
创建TCP套接字
#include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
创建UDP套接字
#include <sys/socket.h> #include <netinet/in.h> #include <netinet/udp.h> udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
04. 套接字地址结构
每个套接字(端点)都有其自己的地址格式,对于 AF_UNIX 套接字来说,它的地址由结构 sockaddr_un 来描述,该结构体定义在头文件 sys/un.h 中,如下:
struct sockaddr_un { sa_family_t sun_family; //套接字域 char sun_path[];//名字 };
而在 AF_INET 域中,套接字地址结构由 sockaddr_in 来指定,该结构体定义在头文件 netinet/in.h 中:
struct sockaddr_in { short int sin_family;//套接字域 unsigned short int sin_port;//端口 struct in_addr sin_addr; //地址 char sin_zero[8]; }
IP 地址结构 sin_addr 被定义如下:
struct in_addr { unsigned long int s_addr; };
05. 附录
- 点赞 2
- 收藏
- 分享
- 文章举报
- Linux网络编程之套接字选项设置
- Linux 网络编程——原始套接字实例:MAC 地址扫描器
- Linux 树莓派 网络编程中服务端通过套接字获取客户端ip地址
- Linux网络编程:原始套接字的魔力【续】
- Linux网络编程之原始套接字-ping协议实现
- [Linux网络编程]Linux网络套接字操作函数--使用socket函数创建套接字
- linux网络设备应用与驱动编程学习笔记(1)——应用编程(套接字)
- Linux网络编程:原始套接字的魔力【上】
- Linux网络编程——端口复用(多个套接字绑定同一个端口)
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- Linux网络编程 套接字
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来处理信息---编写一个单进程非阻塞多客户的套接字客户端
- Linux网络编程:原始套接字的魔力【续】
- Linux网络编程:原始套接字的魔力【下】
- [Linux网络编程]Linux网络套接字操作函数--使用bind函数绑定套接字
- Linux网络编程之socket:unix域套接字编程与socketpair函数
- Linux 网络编程——原始套接字实例:MAC 地址扫描器
- linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时
- linux网络编程之套接字/TCP/IP
- linux 网络编程--原始套接字(下)