python的网络变成比c语言简单许多, 封装许多底层的实现细节, 方便程序员使用的同时, 也使程序员比较难了解一些底层的东西, 我觉得学网络编程
还是用c语言更好一点.
写这篇博文, 也希望回顾并整理一下以前学过的c语言和linux下一些东西, 会将一些Linux网络编程的函数和Python网络变成函数做一个简单的对照, 方便记忆
1. Socket套接字的概念
Socket(翻译为套接字, 我觉得很挫)
,是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户
。它是网络进程的ID。网络通信,归根到底还是进程间的通信(不同计算机上的进程间通信, 又称进程间通信, IP协议进行的主要是端到端通信)。在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。两个进程通信时,首先要确定各自所在的网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中的哪一个进程进行通信,因此套接口中还需要包括其他的信息,也就是端口号(PORT)。在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一一对应关系。
所以,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程.
端口号的范围从0~65535,一类是由互联网指派名字和号码公司ICANN负责分配给一些常用的应用程序固定使用的“周知的端口”,其值一般为0~1023, 用户自定义端口号一般大于等于1024, 我比较喜欢用8888
每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket来实现的
1.1. Socket类型
socket类型在Liunx和Python是一样的, 只是Python中的类型都定义在
socket模块
中, 调用方式socket.SOCK_XXXX
- 流式socket(SOCK_STREAM)
用于TCP通信
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性
- 数据报socket(SOCK_DGRAM)
用于UDP通信
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP
- 原始socket(SOCK_RAW)
用于新的网络协议实现的测试等
原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以, 其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
2. Socket编程
2.1. TCP通信
TCP通信的基本步骤如下:
服务端:socket—bind—listen—while(True){—accept—recv—send—-}—close
客户端:socket———————————-connect—send—recv——-close
socket函数
使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#Linux int socket(int domain, int type, int protocol); domain:AF_INET:Ipv4网络协议 AF_INET6:IPv6网络协议 type : tcp:SOCK_STREAM udp:SOCK_DGRAM protocol : 指定socket所使用的传输协议编号。通常为0. 返回值:成功则返回套接口描述符,失败返回-1。 #python socket.socket([family[, type[, proto]]]) family : AF_INET (默认ipv4), AF_INET6(ipv6) or AF_UNIX(Unix系统进程间通信). type : SOCK_STREAM (TCP), SOCK_DGRAM(UDP) . protocol : 一般为0或者默认 如果socket创建失败会抛出一个socket.error异常 |
2.1.1. 服务器端函数
bind函数
将套接字绑定到地址, python下,以元组(host,port)的形式表示地址, Linux下使用sockaddr_in
结构体指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#Linux int bind(int sockfd, struct sockaddr * my_addr, int addrlen); sockfd : 前面socket()的返回值 my_addr : 结构体指针变量 ##### struct sockaddr_in //常用的结构体 { unsigned short int sin_family; //即为sa_family AF_INET uint16_t sin_port; //为使用的port编号 struct in_addr sin_addr; //为IP地址 unsigned char sin_zero[8]; //未使用 }; struct in_addr { uint32_t s_addr; }; #### addrlen : sockaddr的结构体长度。通常是计算sizeof(struct sockaddr); 返回值:成功则返回0,失败返回-1 #python s.bind(address) s为socket.socket()返回的套接字对象 address为元组(host,port) host: ip地址, 为一个字符串 post: 自定义主机号, 为整型 |
listen函数
使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接
1 2 3 4 5 6 7 8 9 10 |
#Linux int listen(int sockfd,int backlog); sockfd : 为前面socket的返回值. backlog : 指定同时能处理的最大连接要求,通常为10或者5。最大值可设至128 返回值:成功则返回0,失败返回-1 #python s.listen(backlog) s为socket.socket()返回的套接字对象 backlog : 操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了 |
accept函数
接受远程计算机的连接请求,建立起与客户机之间的通信连接。服务器处于监听状态时,如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。
1 2 3 4 5 6 7 8 9 10 11 |
#Linux int accept(int skquote> 写这篇博文, 也希望回顾并整理一下以前学过的c语言和linux下一些东西, 会将一些Linux网络编程的函数和Python网络变成函数做一个简单的对照, 方便记忆 1. Socket套接字的概念
每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket来实现的 1.1. Socket类型
2. Socket编程2.1. TCP通信TCP通信的基本步骤如下: TCP
socket函数
2.1.1. 服务器端函数bind函数
listen函数
accept函数
|