Python Socket编程简介

0x01 Socket是什么


Socket是一种进程间通信的方式,用来实现不同主机之间的通信。 Socket的英文原义是“孔”或“插座”,通常称作套接字。
Socket的编程分为客户端相关的和服务器端相关的,客户端用来请求,服务器端则响应请求。

0x02 Socket客户端编程


使用Socket模块

import socket #导入socket模块

创建一个socket

import socket


socket.socket(socket.AF_INET, socket.SOCK_STREAM)

需要创建一个socket,只需要调用socket模块的socket函数就可以了
即使用socket.socket()

官方文档介绍:
Create a new socket using the given address family, socket type and protocol number. The address family should be AF_INET (the default), AF_INET6 or AF_UNIX. The socket type should be SOCK_STREAM (the default), SOCK_DGRAM or perhaps one of the other SOCK_ constants. The protocol number is usually zero and may be omitted in that case.

函数原型:socket.socket(Address_Family, Type, protocol_number)

  • AddressFamily:地址族,可选的有:
    • socket.AF_INET(Internet进程间通信)
    • socket.AF_UNIX(同一机器的进程间通信)
    • socket.AF_INET6(同样是Internet间的,IPV6的进程间通信)
  • Type:套接字类型,有:
    • socket.SOCK_STREAM(流式套接字,TCP协议多用)
    • SOCK_DGRAM(数据报套接字,UDP协议多用)
  • protocol_number:协议数,默认是0,如果不改变或者不写就使用默认值。

若创建成功,该函数返回一个套接字,否则将得到一个socket.error异常,可以在try-catch块中做处理。

连接服务器

我们可以通过socket.gethostbyname来从一个域名得到其IPv4的地址。

python官方文档说明:
Translate a host name to IPv4 address format. The IPv4 address is returned as a string, such as ‘100.50.200.5’. If the host name is an IPv4 address itself it is returned unchanged. See gethostbyname_ex() for a more complete interface. gethostbyname() does not support IPv6 name resolution, and getaddrinfo() should be used instead for IPv4/v6 dual stack support.

函数原型:socket.gethostbyname(hostname)

参数:

  • hostname:域名,比如www.bing.com,www.baidu.com之类的字符串

函数返回一个由ip地址组成的字符串,例如‘100.50.200.5’

获取到IP地址以后就可以进行连接了,连接使用connect方法。

函数原型:socket.connect(address)

官方文档介绍:
Connect to a remote socket at address. (The format of address depends on the address family — see above.)

参数:

  • address:一个tuple,(remote_ip, port),即IP地址和端口

而这个方法应该由之前创建的套接字来调用。

import socket

try:
    sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = 'www.bing.com'
    port = 80
    remote_ip = socket.gethostbyname(host)
    sckt.connect((remote_ip, port))
    print "socket connection success!"
except socket.error, socket.gaierror:
    print "connection failed"

这样就可以完成一个服务器的连接了

向服务器发送数据

连接到服务器成功以后,向服务器请求数据,再得到服务器的数据才是我们的目的。
发送数据主要涉及到两个函数:
socket.send()和socket.sendall()

  • socket.send(string[,flags])
  • Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data.(向套接字发送数据。套接字必须和远程套接字有连接。可选的flags参数和recv函数有一样的意义,返回已经发送的字节数。应用程序应该负责检测所有的数据是不是已经都被发送,如果只有部分数据被发送,应用程序需要试图发送剩下的数据)
  • socket.sendall(string[, flags])
  • Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.(发送数据到套接字。套接字必须和远程套接字有连接。可选的flags参数和recv函数有同样的意义。和send()函数不一样的是,这个方法会继续发送字符串里的数据知道要么全部被发送要么发生了错误。成功发送后返回None。如果发生错误将会触发一个异常,以及没有任何办法可以知道有多少数据被成功发送)

从服务器接收数据

发送数据之后就应该接收服务器的数据了,接收数据有多个函数可选:

  • socket.recv(bufsize[, flags])
    • Receive data from the socket. The return value is a string representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero(从套接字接收数据,返回值是接收到的数据的字符串。最大可接收的数量由bufsize指定,建议Bufsize使用2的指数比如4096之类的)
  • socket.recvfrom(bufsize[, flags])
    • Receive data from the socket. The return value is a pair (string, address) where string is a string representing the data received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)(从套接字接收数据,返回一个字符串和地址对,字符串代表已接收数据,地址是发送数据的套接字地址)
  • socket.recvfrom_into(buffer[, nbytes[, flags]])
    • Receive data from the socket, writing it into buffer instead of creating a new string. The return value is a pair (nbytes, address) where nbytes is the number of bytes received and address is the address of the socket sending the data. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)(从套接字接收数据,并且写入缓冲区而不是新建立一个字符串,返回一个pair,第一个是nbytes第二个是address,nbytes即已接收到的数据字节数,第二个则是发送数据的地址)
  • socket.recv_into(buffer[, nbytes[, flags]])
    • Receive up to nbytes bytes from the socket, storing the data into a buffer rather than creating a new string. If nbytes is not specified (or 0), receive up to the size available in the given buffer. Returns the number of bytes received. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.(从套接字接收最多nbytes字节,并且存进缓冲区。返回已经接收到的字节数)

实例:

import socket

try:
    sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = 'www.bing.com'
    port = 80
    remote_ip = socket.gethostbyname(host)
    sckt.connect((remote_ip, port))
    print "socket connection success!"
    message = "GET / HTTP/1.1\r\n\r\n" #向服务器发送get请求
    sckt.sendall(message)
    response = sckt.recv(4096)
    print response
except socket.error, socket.gaierror:
    print "connection failed"

关闭连接

调用socket.close即可

sckt.close()

Socket服务器端编程

服务器端和客户端Socket不同的是,服务器处理Socket,其工作有:

  • 绑定socket
  • 监听连接
  • 建立连接
  • 接收和发送数据

绑定socket

使用bind函数

  • socket.bind(address)
  • Bind the socket to address. The socket must not already be bound. (The format of address depends on the address family — see above.)(绑定套接字到地址,套接字不能已经被绑定过)(注:此处的地址和之前的地址一样,可以是一个tuple,(HOST, PORT)这样的形式指明主机和端口)

监听连接

使用listen函数

  • socket.listen(backlog)
  • Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 0; the maximum value is system-dependent (usually 5), the minimum value is forced to 0(监听套接字的连接。backlog参数指明最大的连接队列的数量而且至少是0。虽大值和系统相关,一般是5,最少被强制安排为0)

接收连接

使用accept函数

  • socket.accept()
    • Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.(接收一个连接,套接字必须被绑定到一个地址,并且正在监听连接。返回值是一个pair:(conn,address),conn是一个新的可用的套接字对象用来发送和接受连接的数据,地址是连接的另一端被绑定在套接字上的地址)

处理连接

处理连接需要我们将处理程序和接收连接的主程序分开处理,所以我们只做一个简单的介绍,不深究其实现。大概方法就是,使用线程。
过程如下:
主程序绑定套接字,监听连接,进入循环,循环中等待接收连接,一旦有连接接入,创建一个线程,在该线程中利用和客户端一样的方式接收和发送数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值