网络编程基础(一)

网络编程基础(一)

一、套接字

1.分类
1.1面向连接的套接字

面向连接的套接字,需要在通信之前就要先建立一个连接,也称为虚拟电路或者流套接字。

实现这种连接类型的主要协议为`传输控制协议TCP`,创建`TCP`套接字必须要使用`SOCK_STREAM`作为套接字类型。

1.2面向无连接的套接字

在通信开始之前不需要进行建立连接,也被称为数据报。

这种连接类型的主要协议为`用户数据报服务UDP`, 创建这种套接字,必须要使用`SOCK_DGRAM`作为套接字类型.

二、基本使用

1.socket模块函数

创建socket的一般语法:

socket(socket_family, socket_type, protocol=0)

eg: TCP
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
eg: UDP
usp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

如果我们使用from socket import *导入socket属性,即将socket属性引入命名空间中,那么就可以使用下面的简短代码创建套接字:

tcp_sock = socket(AF_INET, SOCK_STREAM)

2.常见的套接字对象方法:

名称 描述
服务器套接字方法
s.bind() 将地址(主机名,端口号对)绑定到套接字上
s.listen() 设置并启动TCP监听器
s.accept() 被动接受TCP客户端的连接,一直等待知道连接到达(阻塞)
客户端套接字方法
s.connect() 主动发起TCP服务器连接
s.connect_ex() connect()的扩展版本,此时会以错误码形式返回问题,而不是抛出异常普通的套接字方法
s.recv() 接收TCP消息
s.recv_into() 接收TCP消息到指定的缓冲区
s.send 发送TCP消息
s.sendall() 完整的发送TCP消息
s.recvfrom() 接收UDP消息
s.recvfrom_into() 接收UDP消息到指定的缓冲区
s.sendto() 发送UDP消息
s.getpeername() 连接到套接字(TCP)的远程地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回给定套接字选项的值
s.setsockopt() 设置给定套接字选项的值
s.shutdown() 关闭连接
s.close() 关闭套接字
s.detach() 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
s.ioctl() 控制套接字的模式(仅仅支持windows系统)
s.functl() 控制套接字的模式(对于POSIX系统)
面向阻塞的套接字方法
s.setblocking() 设置套接字的阻塞或者非阻塞模式
s.settimeout() 设置阻塞套接字的操作的超时时间
s.gettimeout() 获取阻塞套接字操作的超时时间
面向文件的套接字方法
s.fileno() 套接字的文件描述符
s.makefile() 创建于套接字关联的文件对象
数据属性
s.family() 套接字家族
s.tyep() 套接字类型
s.proto() 套接字协议

三、创建服务器和客户端

(一).TCP的Server和Client

1.TCP server

伪代码模版块:
ss = socket()               # 创建服务器套接字
ss.bind()                   # 套接字与地址绑定 
ss.listen()                 # 监听连接
inf_loop:                   # 服务器无限循环
    cs = ss.accept()        # 接收客户端连接
    comm_loop():            # 通信循环
        cs.recv()/cs.send() # 对话(接收/发送)
    cs.close()              # 关闭客户端套接字
ss.close()                  # 关闭服务器套接字 (可选)

简述:

1、所有的套接字通过使用socket.socket()函数来创建的。
2、由于服务器需要占用一个端口并等待客户端的请求,所以其必须绑定 到一个本地地址,TCP是面向连接的,在其开始操作之前,必须安装一些基本设施。
3、监听连接后,服务器就可以开始他的无线循环
4、调用accept()之后,开启了(单线程)服务器,等待连接。默认下,accept()是阻塞的。
5、服务器接收连接之后,就会返回(利用accept())一个独立的客户端套接字,用来进行数据交换。
客户端关闭连接之后,不会影响服务端的无线循环。但可以使用close()函数主动退出。

Demo:

# 一个TCP-server,
# 接收客户端的信息,并打上时间戳,返回给client
# 返回格式: time + data
# 
# coding=utf-8

from socket import *
from time import ctime

# 相关属性
host = ''   # 变量是空白的,对bind()函数的标识,其可以使用任何可用地址。
port = 21567
buffer_size = 1024
address = (host, port)

# 建立连接
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.bind(address)
tcp_server.listen(5)   # 同时连接的最大值

# 逻辑
while True:
    print ("[+] waiting for connection...")
    tcp_client, address = tcp_server.accept()  # 得到连接客户端的套接字
    print ("[+] ...connected from:", address)

    while True:
        data = tcp_client.recv(buffer_size)  # 得到客户端发送的数据
        if not data:
            break
        tcp_client.send('[M] [%s] %s' % (ctime(), data))  # 返回已处理数据

    tcp_client.close()
tcp_server.close()   # 这一行永远不会执行

2.TCP Client

# 伪代码板块

cs = socket()              # 创建客户端套接字
cs.connect()               # 尝试连接服务器
comm_loop:                 # 通信循环
    cs.send()/cs.recv()    # 对话(发送/接收)
cs.close()                 # 关闭客户端套接字

简述:

1、利用socket.socket()创建的
2、利用Connect连接到服务器

Demo:

# coding=utf-8

from socket import *

# 属性
host = 'localhost'
port = 21567
buffer_size = 1024
address = (host, port)

# 连接
tcp_client = socket(AF_INET, SOCK_STREAM)
tcp_client.connect(address)

# 逻辑处理
while True:
    data = raw_input('>> ')
    if not data:
        break
    tcp_client.send(data)
    data = tcp_client.recv(buffer_size)
    if not data:
        break
    print data

tcp_client.close()

(二).UDP的Server和Client

1. UDP server

# 伪代码板块

ss.socket()           # 创建服务器套接字
ss.bind()             # 绑定服务器套接字
inf_loop:             # 服务器无限循环
    cs = ss.recvfrom()/ss.sendto()  # 接收/发送
ss.close()            # 关闭服务器套接字

简述:

1、对于UDP的连接,不需要很多设置,在这里,它与TCP服务器最显著的差别: 没有为了确认成功通信而使客户端连接到一个独立的套接字

Demo:

# coding=utf-8

from socket import *
from time import ctime

# 属性
host = ''      # 变量是空白的,对bind()函数的标识,其可以使用任何可用地址。
port = 21567
buffer_size = 1024
address = (host, port)

udp_server = socket(AF_INET, SOCK_DGRAM)
udp_server.bind(address)

while True:
    print ("[+] waiting for connection...")
    data, address = udp_server.recvfrom(buffer_size)
    udp_server.sendto("[M] [%S] %s " % (ctime(), data), address)
    print "[+] ...received from and returned to:", address

udp_server.close()

2.udp client

# 伪代码
cs = socket()    # 创建客户端套接字
comm_loop:       # 通信循环
    cs.sendto()/cs.recvfrom    # 对话(发送/接收)
cs.close()       # 关闭客户端套接字

简述:

对于UDP连接,一旦创建了套接字对象,就进入对话循环中通信结束时,就会关闭套接字

Demo:

# coding=utf-8

from socket import *

# 属性
host = 'localhost'
port = 21567
buffer_size = 1024
address = (host, port)

# 连接
udp_client = socket(AF_INET, SOCK_DGRAM)

while True:
    data = raw_input(">> ")
    if not data:
        break
    udp_client.sendto(data, address)
    data, address = udp_client.recvfrom(buffer_size)
    if not data:
        break
    print data

udp_client.close()

四、有关socket模块的属性介绍

在下面给出一些socket常见的属性:

属性名称 描述
数据属性
AF_UNIX、AF_INET、AF_INET6、AF_NETLINK、AF_TIPC python中所支持的套接字地址家族
SO_STREAM、SO_DGRAM 套接字类型(TCP-流、UDP-数据报)
has_ipv6 指示是否支持IPV6的布尔标记
异常
error 套接字的相关错误
herror 主机和地址相关错误
gaierror 地址相关错误
timeout 超时时间
函数
socket() 以给定的地址家族、套接字类型和协议类型(可选)创建一个套接字对象
socketpair() 以给定的地址家族、套接字类型和协议类型(可选)创建一对套接字对象
create_connection() 常规函数,它接收一个地址(主机号、端口)对,返回套接字对象
fromfd() 以一个打开的文件描述符创建一个套接字对象
ssl() 通过套接字启动一个安全套接字层连接,不执行证书认证
getaddrinfo() 获得一个五元组序列形式的地址信息
getnameinfo() 给定一个套接字地址,返回(主机号、端口号)二元组
getfqdn() 返回完整的域名
gethostname() 返回当前主机名
gethostbyname() 将一个主机名映射到它的IP地址
gethostbyname_ex() gethostbyname()的扩展版本,它返回主机名、别名主机集合和IP地址列表
gethostbyaddr() 将一个IP地址映射到DNS信息;返回与gethostbyname_ex()相同的三元组
getserverbyname()/getserverbyport() 将一个服务名映射到一个端口,或者反过来;对于任何一个函数来说,协议名都是可选的。
ntohl()/ntohs() 将来自网络的整数转换为主机字节顺序
htonl()/htons() 将来自主机的整数转换为网络字节顺序
inet_aton()/inet_ntoa() 将IP地址八进制字符串转换为32位的包格式,或者反过来;仅使用与IPV4地址
inet_pton()/inet_ntop() 将IP地址字符串转换为打包的二进制格式,或者反过来。(同时适用IPV4、IPV6)
getdefaulttimeout() 以秒(浮点数)为单位返回默认套接字超时时间
setdefaulttimeout() 以秒(浮点数)为单位设置默认套接字超时时间

以上就是对于网络编程基础的介绍,接下来,会以实现一个类QQ的通信进行练习。(见二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容