3 建立socket - establish socket 4 import socket 5 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 6 # s = 通信类型(type) + 协议家族(protocol) 7 # AF_INET = IPV4 ; AF_INET6 = IPV6 8 # SOCK_STREAM = TCP ; SOCK_DGRAM UDP 10 s.connect(( " www.zzyzz.top " ,80 )) 11 # s.connect((IP,PORT)) 12 # python 中 socket 对象的 connect()方法会利用 DNS 把域名解析成 IP 14 寻找端口号 - detect the port 15 port = socket.getservbyname( ' http ' , ' TCP ' ) 16 # 查询系统特定服务的端口号, 小于1024 由 IANA(Internet Assigned Numbers Authority)分配. 17 # socket.getservbyname( protocol name, port name) 19 从 socket 获取信息 - get info. from socket 20 sname = s.getsockname() 21 # 返回一个 tuple (client IP, client port), 对于客户端, 端口号由操作系统分配 22 pname = s.getpeername() 23 # 得到一个 tuple (sever IP, server port) 25 socket 通信 - communication via socket 26 python 提供了 2 种通信方式:socket 对象 和 文件类对象 27 socket 对象的方法, 28 send() 29 sendto() 30 recv() 31 recvfrom() 33 文件类对象对应的方法, 34 read() 35 write() 36 readline() 38 异常处理 - process exceptions 39 python 的 socket 模块定义了 4 种可能出现的异常, 40 socket.error , 与 I/ O 和 通信 有关的异常 41 socket.gaierror , 与 查询地址信息有关的异常 42 socket.herror , 与其他地址错误相关的异常 43 socket.timeout , 超时有关的异常(在一个 socket 对象上调用 settimeout()) 45 例子, 46 try : 47 s.connect(( " www.zzyzz.top " , 80 )) 48 except socket.gaierror as e: 49 print ( " Address related error : %s " % e) 50 except socket.error as e: 51 print ( " Connection error : %s " % e) 53 output, 54 # 1 Address related error : [Errno 11001] getaddrinfo failed -> socket.gaierror 55 # 2 Connection error : [WinError 10060] A connection attempt -> socket.error 56 failed because the connected party did not properly respond 57 after a period of time, or established connection failed 58 because connected host has failed to respond 59 socket 模块可以把域名转换成IP地址(DNS), 有可能看到两中错误, 60 一种是域名错误,会得到 socket.gaierror , 另一种是链接远程 server 的 socket.error. 62 完整的 socket 建立的例子, 63 socket 对象类通信示例, 64 import socket 66 try : 67 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 68 except socket.error as e: 69 print ( " Error at creating socket : %s " % e) 71 try : 72 s.connect(( " www.zzyzz.top " , 80 )) 73 except socket.gaierror as e: 74 print ( " Address related error : %s " % e) 75 except socket.error as e: 76 print ( " Connection error : %s " % e) 78 try : 79 s.send( " HELLO THERE! " .encode()) 80 except socket.error as e: 81 print ( " Error at sending data : %s " % e) 83 try : 84 s.shutdown(1 ) 85 except socket.error as e: 86 print ( " Error at sending data(shutdown) : %s " % e) # 数据只有在调用了 shutdown() 方法后才能确保被发送. 88 while 1 : 89 try : 90 recv = s.recv(1024 ) 91 except socket.error as e: 92 print ( " Error at receiving data : %s " % e) 93 if not len(recv): 94 print ( " Data received " ) 95 break 97 文件类对象通信示例, 98 可以通过 makefile() 方法从 socket 对象得到一个文件类对象,实际上这个文件类对象调用的还是 socket, 99 所以由文件类对象产生的异常和 socket 对象的 send() 和 recv() 方法是一样的. 100 import socket 101 try : 102 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 103 except socket.error as e: 104 print ( " Error at creating socket : %s " % e) 106 try : 107 s.connect(( " www.zzyzz.top " , 80 )) 108 except socket.gaierror as e: 109 print ( " Address related error : %s " % e) 110 except socket.error as e: 111 print ( " Connection error : %s " % e) 113 FH = s.makefile( ' rwb ' ,0) # 第一参数是 模式:读,写,读写; 第二个参数是 buffer size 114 try : 115 FH.write( " HELLO THERE! " .encode()) 116 except socket.error as e: 117 print ( " Error at sending data : %s " % e) 119 try : 120 FH.flush() # 由于在 makefile() 方法指定了 buffer size 是 0, 121 # 所以这例的 flush() 方法的调用时非必须地 122 except socket.error as e: 123 print ( " Error at sending data(flush) : %s " % e) 125 try : 126 s.shutdown(1) # 即使调用 makefile(), 也要保存 socket 对象. 127 # makefile() 返回的文件类对象并不提供对 shutdown() 的调用 128 # 所以要保存原始 socket 对象, 并在其上调用 shutdown() 129 # 数据只有在调用了 shutdown() 方法后才能确保被发送. 130 s.close() 131 except socket.error as e: 132 print ( " Error at sending data(shutdown) : %s " % e) 134 while 1 : 135 try : 136 recv = FH.read(1024 ) 137 except socket.error as e: 138 print ( " Error at receiving data : %s " % e) 139 if not len(recv): 140 print ( " Data received " ) 141 break
  Summarize,
  对于客户端来说,建立一个 TCP 链接的过程分两步,
  1, 建立 socket 对象
  s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  2, 调用 connect() 方法, 建立跟服务断(server)的链接.
  s.connect(("www.zzyzz.top", 80))