提示:以下是本篇文章正文内容,下面案例可供参考
通信双方必须知道对方的标识。互联网上计算机的唯一标识就是IP地址。通常是网卡。
IP 协议负责把数据从一台计算机通过网络发送到另一台计算机上。数据被分割成一小块,然后通过IP包发送过去。 IP包的特点是按快发送,途径多个路由,但不保证能到达,也不保证顺利到达。
IP地址实际上是一个32位整数(IPv4),以字符串表示的IP地址实际上是把32位整数按8位分组后的数字表示(如192.165.0.1),目的是便于阅读。
TCP协议是建立在IP协议之上的,TCP协议负责在两台计算机之间建立可靠连接,保证数据顺利到达。
一个IP包除了包含传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。 而端口的作用是区分送过来的IP包是给那个程序的。
网络编程中有一个基本组件----套接字(socket)
套接字为特定的网络协议(如TCP/IP,UDP/IP)套件对上的网络应用程序提供当前可移植标准的对象。套接字允许程序接收数据并进行连接,为了建立通信通道,网络通信的每个端点拥有一个套接字对象级为重要。
该处使用socket()函数来创建套接字。
语法格式
socket.socket([family[,type[,protoco]]])
socket.bind(address)
address 必须是一个双元素元组。参数为主机名或ip地址加端口。
请求方式如下:
socket.listen(backlog)
backlog 用于指定最多连接数,至少为一。接到连接请求后,这些请求必须排队,如果已满,就拒绝请求。
调用accept方法时,socket会进入等待(或阻塞)状态。客户请求连接时,accept方法建立连接并返回服务器。accept方法返回一个含有两个元素的元组,如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客户通信;第二个元素(address)是客户的互联网地址。
服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recy方法从客户接收信息。调用reev时,必须指定一个整数控制本次调用所接收的最大数据量。recy方法在接收数据时会进入blocket状态,最后返回一个字符串,用于表示收到的数据。如果发送的量超过recy允许的量,数据就会被截断。多余的数据将缓冲于接收端。以后调用recy时,多余的数据会从缓冲区删除。
import socket #引入套接字模块
#因为服务器需要同时响应多个客户端的请求,每一个连接都需要一个进程或新线程#1处理,否则一次只能服务一个客户
import threading #引入进程模块
import time
def socket_server():
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#步骤1
host = socket.gethostname() #获取本地主机名
port = 5555 #端口号,0-1024 是标准的不能随意使用,1025-9999 可以随意#1使用
server_socket.bind((host,port)) #参数必须是双元素元组,步骤2
server_socket.listen(5) #步骤3
while True:
#会返回一个含有两个元素的元组。第一个元素是一个新的 socket 对象
#服务器通过它与客户端通信;第二个元素是客户的互联网地址
sock,addr = server_socket.accept() #步骤4
# threading.Thread(target =1,args =2)1 对于函数,2是该函数需要的参数
t = threading.Thread(target = tcp_link,args = (sock,addr))
t.start()
def tcp_link(sock,addr):
print('Accept new connection from %s:%s...'% addr)
sock.send('欢迎学校 Python 网络编程!'.encode('utf-8')) #send 发送数据
while True:
data = sock.recv(1024) #recv 接收数据,最大为一个字节 1024
time.sleep(1)
if not data or data.decode('utf-8')=='exit':
break;
sock.send(("Hello,%s!"%data.decode('utf-8')).encode('utf-8'))
sock.close()
print('connection from %s:%s closed.'%addr)
def main():
socket_server()
if __name__ =='__main__':
main()
1.创建一个socket以连接服务器。socket=socket.socket(family,type)
2.使用socket 的connect 方法连接服务器。 socket.connect((hoat,port))
3.通过send()与recv()方法通信。
4.结束后,调用socket的close方法以关闭连接。
代码案列:
import socket
def socket_client():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = socket.gethostname()
port = 5555
s.connect((host,port)) #连接服务器,指定主机和端口
print(s.recv(1024).decode('utf-8'))
for data in ['小青','小白','小花']:
s.send(data.encode('utf-8'))
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
def main():
socket_client()
if __name__ =='__main__':
main()
1.域名可以自动转换到IP地址。
2.作为服务器,提供服务时端口号必须固定下来。由于我们想要访问网页,因此新浪提供网页服务的服务器必须把端口号固定在80端口。80端口是Web服务的标准端口。其他服务都有对应的标准端口号,如SMTP服务是25端口,FTP服务是21端口,等等。端口号小于1024的是Internet标准服务端口,端口号大于1024的可以任意使用,
函数 | 描述 |
---|---|
bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
listen() | 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
函数 | 描述 |
---|---|
connect() | 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
函数 | 描述 |
---|---|
recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
sendall() | 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
recvfrom() | 接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 |
sendto() | 发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。 |
close() | 关闭套接字 |
getpeername() | 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 |
getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,port) |
setsockopt(level,optname,value) | 设置给定套接字选项的值。 |
getsockopt(level,optname[.buflen]) | 返回套接字选项的值。 |
settimeout(timeout) | 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()) |
gettimeout() | 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。 |
fileno() | 返回套接字的文件描述符。 |
setblocking(flag) | 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
makefile() | 创建一个与该套接字相关连的文件 |
2.在左侧有tcp和udp的客户端或服务端的快捷按钮,上方有【创建】【删除】【退出】等选项按钮。
4 我们先来建立TCP的测试服务端。点击【TCP Server】再点击【创建】。
选择一个监听端口,这里我们使用6001作为服务端的监听端口。
建立完成后,服务端会自动启动,软件会显示【启动监听】的状态。
建立完成后,服务端会自动启动,软件会显示【启动监听】的状态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
我们可以检测一下本机的6001端口是否已经打开。在DOS窗口中输入命令【netstat -a】,可以在列表中看到本机的6001端口的状态为listening的状态,表示本机的6001端口正处于监听的状态。
在DOS窗口中输入命令【telnet 192.168.0.140 6001】来登录本地的6001端口。 注意:192.168.0.140 6001 要根据软件中本机的编号来写。
window下 无法执行 telnet 命令的解决方法
1.打开设置中应用。
2.打开右上角的
3.
4.找到telnet 服务,勾选就好
点击回车键,就可以成功登录6001端口。在测试软件中就可以看到状态是已连接的状态,同时也可以看到对方的ip就是本地ip。
在软件的发送窗口中输入1234567890,点击发送后,在DOS窗口中就可以看到软件发送过来的数据了。
若想发送中文不要勾选16进制。