文章出自:Python socket – network programming tutorial by Silver Moon
原创译文,如有版权问题请联系删除。
Network programing in Python:
Part1: Programing sockets client.
这是一篇在Python中Socket网络编程的快速指南,实现过程非常接近于C语言。
总体来说,在电脑网络通信完成的背后,Sockets是非常基础的“事情”,比如说,当你在浏览器输入"www.baidu.com", 实际上它需要先打开Socket并且连接到baidu.com 然后才将结果呈现给你。和任何其他的通讯一样,比如说:Gtalk 或 Skype,任何网络通信都是要通过Socket.
在本次的快速指南中,将要在Python中使用TCP Socket编程。当然你也可以在Python中使用UDP Socket编程,具体参考:program udp sockets in python.
Before you begain:
这篇教程开始之前,假设所有读者都已经具备了Python的基础编程知识。
So, Let's do this.
Creating a Socket:
首先,我们先创建一个Socket,然后socket.socket方法就有了这样的功能:
例如:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- #Socket client example in python import socket #for sockets #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print ('Socket Created')
方法 socket.socket 创建了一个socket 并返回一个socket可以用于和其他socket相关的描述。
上面的代码将会创建一个socket,拥有了下面的属性...
Address Family : AF_INET (this is IP version 4 or IPv4)
Type : SOCK_STREAM (this means connection oriented TCP protocol)
Error Handling:
如果任何socket方法异常或失败,Python将会抛出一个异常然后调用socket.error。
#handling errors in python socket programs import socket #for sockets import sys #for exit try: #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error as msg: print ('Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]) sys.exit(); print ('Socket Created')
OK, so 你已经成功创建了一个socket,接下来我们将会尝试连接一个server,当然我们可以连接www.baidu.com。
Connect to a Server:
我们通过已知的端口连接远程服务器,有2件事是必备的,其中分别是IP地址和端口号,所以你在建立远程连接之前必须知道IP地址和端口号,在这里我们使用www.baidu.com作为连接的服务器。
a>.首先,获取远程服务器或连接的IP地址
在开始connect之前,必须获取IP地址,在Python中获取IP地址需要一句很简单的代码。
#!/usr/bin/python import socket #for sockets import sys #for exit try: #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #except socket.error,msg, error msg: ", variable" not allowed in 3.x - use "as variable" instead. except socket.error as msg: print ('Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]) sys.exit(); print ('Socket Created') host = 'www.baidu.com' try: remote_ip = socket.gethostbyname( host ) except socket.gaierror: #could not resolve print ('Hostname could not be resolved. Exiting') sys.exit() print ('Ip address of ' + host + ' is ' + remote_ip)
b>.现在我们已经得到远程服务器或系统的IP地址,可以使用connect方法和端口创建连接。
实例:
#!/usr/bin/python import socket #for sockets import sys #for exit try: #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #except socket.error,msg, error msg: ", variable" not allowed in 3.x - use "as variable" instead. except socket.error as msg: print ('Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]) sys.exit(); print ('Socket Created') host = 'www.baidu.com' port = 80 try: remote_ip = socket.gethostbyname( host ) except socket.gaierror: #could not resolve print ('Hostname could not be resolved. Exiting') sys.exit() print ('Ip address of ' + host + ' is ' + remote_ip) #connect to remote server s.connect((remote_ip,port)) print ('Socket connect ' + host + ' on ip ' + remote_ip)
结果视图:
OK,现在我们创建了一个Socket实例并且也已经成功连接了,当然你也可以尝试连接不同的端口(PORT),但是你会发现连接是失败的,因为其他的端口并不是公开的,依据这样的逻辑,你可以做一个端口扫描器。
接下来我们可以尝试发送一些数据到远程服务器。
Sending Data:
方法:sendall 被用来发送数据,我们来尝试发送数据到baidu.com吧。
#!/usr/bin/python import socket #for sockets import sys #for exit import array try: #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #except socket.error,msg, error msg: ", variable" not allowed in 3.x - use "as variable" instead. except socket.error as msg: print ('Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]) sys.exit(); print ('Socket Created') host = 'www.baidu.com' port = 80 try: remote_ip = socket.gethostbyname( host ) except socket.gaierror: #could not resolve print ('Hostname could not be resolved. Exiting') sys.exit() print ('Ip address of ' + host + ' is ' + remote_ip) #connect to remote server s.connect((remote_ip,port)) print ('Socket connect ' + host + ' on ip ' + remote_ip) #sending some data to romete server #socket sending must be bytes message = b"GET / HTTP/1.1\r\n\r\n" try: #sending message s.sendall(message) except socket.error: #Send failed print('Send failed') sys.exit(); print('Sending data successfully')
在上面的例子中,我们首先连接到远程服务器并且发送了bytes字节的message(b"GET / HTTP/1.1\r\n\r\n"),信息实际上是以“http command”访问网站的。现在我们已经发送了一些数据,现在该是时机接收数据了。
Receiving Data:
在Python的socket中,方法“recv”是用来接收返回数据的,下面的例子将会展示接收从远程服务器返回的数据。
实例:
#!/usr/bin/python import socket #for sockets import sys #for exit import array try: #create an AF_INET, STREAM socket (TCP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #except socket.error,msg, error msg: ", variable" not allowed in 3.x - use "as variable" instead. except socket.error as msg: print ('Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]) sys.exit(); print ('Socket Created') host = 'www.baidu.com' port = 80 try: remote_ip = socket.gethostbyname( host ) except socket.gaierror: #could not resolve print ('Hostname could not be resolved. Exiting') sys.exit() print ('Ip address of ' + host + ' is ' + remote_ip) #connect to remote server s.connect((remote_ip,port)) print ('Socket connect ' + host + ' on ip ' + remote_ip) #sending some data to romete server #socket sending must be bytes message = b"GET / HTTP/1.1\r\n\r\n" try: #sending message s.sendall(message) except socket.error: #Send failed print('Send failed') sys.exit(); print('Sending data successfully') #receiving data reply = s.recv(1024) print( reply,'We got some datas as :', end='\n')
结果:
我们可以看到,www.baidu.com回应了我们的请求,现在我们已经成功的接收到回应,是时候关闭我们的socket了。
Close Socket:
方法: close 用来关闭socket。
s.close()
that's it! 原文作者好傲娇。
Summary:
通过上面的例子,我们掌握了:
1>.在Python中如何创建一个Socket.
2>.连接到远程服务器
3>.发送数据
4>.接收数据
对于浏览器打开www.baidu.com的请求过程,通过上面的例子,可以帮助你深刻的理解这一过程。