# socket 是一套接口,封装了网络编程协议
socket是位于应用层与传输层之间的一个抽象层
专门把传输层以下的协议封装成接口提供给应用层使用
应用只需要调用socket的接口或者说按照socket的标准编写
程序,写出的程序自然是遵循tcp/ip协议
1, #===================================server.py
import socket
#作为服务器必须明确自己的IP和端口号,并且不应该改变
#参数1 指定socket类型 socket.AF_INET 表示网络类型
#参数2 指定的传输协议为 socket.SOCK_STREAM 表示为TCP协议 socket.SOCK_DGRAM协议表示UDP协议
# server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #1,买电话机
#默认是网络类型 TCP协议
server = socket.socket()
#127.0.0.1 这叫回送地址 表示当前电脑本身
# ip 一定是本机IP 本机可能会有多个IP(无线|有线)
#注意:需要参数就是一个元组,端口就是普通参数
server.bind(('127.0.0.1',8989)) #2,插入手机卡
#无论是服务器还是客户端 , 都是socket类型
#开始监听1688端口 盯着这个端口看以后没有数据过去
server.listen(4) #3,手机开始待机
#接受链接请求
#第一个表示客户端的socket 第二个客户端的地址信息
cilent,add = server.accept() #4,接电话
#5,收发数据
data = cilent.recv(1024)
print(data.decode('utf-8'))
cilent.send('你好,我是服务端!'.encode('utf-8'))
server.close()
#=================================client.py
import socket
#买个电话
cilent = socket.socket()
# 作为客户端 ip 和端口可以变化,所有系统会自动分配随机端口给客户端
cilent.connect(('127.0.0.1',8989))
#开始通话
#发送数据,注意发送的内容只能是二进制 bytes
cilent.send('hello ,我是客户端'.encode('utf-8'))
#接收数据 单位为字节
data = cilent.recv(1024)
print(data.decode('utf-8'))
cilent.close()
2 ,#==========================client.py
import socket
client = socket.socket()
#connect 本质实在进行三次握手,也是一个数据传输的过程,如果服务器没有立马响应,也会阻塞
client.connect(('127.0.0.1',8989)) #三次握手
print('握手成功! client')
#发送数据,本质是把数据交给操作系统来进行发送,一旦数据交给了操作系统,后续的发送
#应用程序就无法控制了,send一般不会卡,当然,如果数据很大就会阻塞
client.send('hello'.encode('utf-8'))
print('发送完成')
#是从操作系统缓存区读取数据,如果当前还没有任何数据,就会进入阻塞
#会一直等到有数据到来,在继续执行
try:
data = client.recv(1024)
print('接受完成')
print(data)
except:
print('服务器 强行下线了')
import time
time.sleep(4)
#客户端执行close是正常关闭链接,会给服务器送空字节,用于表示要断开链接
client.close()
print('客户端关机了')
#==========================server.py
import socket
server = socket.socket()
server.bind(('127.0.0.1',8989)) #只有服务器需要绑定
server.listen(4)
#accept 是一个阻塞函数 会一直等到有客户端链接过来,在继续执行
cilent,addr = server.accept() #完成了三次握手
print(cilent,addr) #('127.0.0.1', 61638)
print('握手成功!')
#收发数据 注意都是用表示客户端的socket来收发数据
cilent.send('world'.encode('utf-8'))
import time
time.sleep(3)
try:
data = cilent.recv(1024)
print('客户端发来的数据',data)
#发送数据时,对方可能也会异常下线,也会抛出异常
#接受数据和发送数据都应该放到try
cilent.send('test'.encode('utf-8'))
except:
print('cilent 下线了')
#断开链接
cilent.close() #完成四次挥手
server.close()
print("服务器关机!")
3 ,加上循环 #=========================client.py
import socket
client = socket.socket()
#指定服务器的端口和ip 客户端的端口系统会自动分配
client.connect(('127.0.0.1',8989))
#添加循环,用来重复接收数据
while True:
#收发的顺序 必须和对面相反,否则会卡死
msg = input('输入内容:')
if not msg:continue
#发送信息
client.send(msg.encode('utf-8'))
print('发送%s完成!'%msg)
#接收信息
data = client.recv(1024)
print('接收到:%s'%data.decode('utf-8'))
client.close()
#=====================================server.py
import socket
server = socket.socket()
server.bind(('127.0.0.1',8989))
server.listen(5)
while True:
client_socket,client_addr = server.accept()
buffer_size = 1024 #缓冲区 就是一个临时的容器
#缓冲区大小 不能随便写,太大会导致内存溢出 ,太小效率低下,在内存能够承受的情况下,可以打一些
while True:
try:
#接收数据
data =client_socket.recv(1024)
#在linux中,对方如果强行下线了,服务器不会抛出异常,只会收到空消息
#得加上以下判断,如果为空则意味着 对方下线了,应该关闭链接,跳出循环
#windows上如果输入Q正常关闭,也会收到空消息不会抛异常会一直循环空,所有if必须要加
if not data:
client_socket.close()
break
print('接收到%s'%data.decode('utf-8')) #解码时必须保证双方统一编码方式
#发送数据,转为大写在发回去
client_socket.send(data.upper())
except ConnectionResetError as e:
print('%s %s'%(client_addr[0],client_addr[1]),e)
#如果对方下线了,那服务器也应该关闭对应的客户端对象
client_socket.close()
break
#通常服务器不会关闭
# server.close()
4 ,加上异常 #==============================client.py
import socket
client = socket.socket()
#connect 本质实在进行三次握手,也是一个数据传输的过程,如果服务器没有立马响应,也会阻塞
client.connect(('127.0.0.1',8989)) #三次握手
print('握手成功! client')
#发送数据,本质是把数据交给操作系统来进行发送,一旦数据交给了操作系统,后续的发送
#应用程序就无法控制了,send一般不会卡,当然,如果数据很大就会阻塞
client.send('hello'.encode('utf-8'))
print('发送完成')
#是从操作系统缓存区读取数据,如果当前还没有任何数据,就会进入阻塞
#会一直等到有数据到来,在继续执行
try:
data = client.recv(1024)
print('接受完成')
print(data)
except:
print('服务器 强行下线了')
import time
time.sleep(4)
#客户端执行close是正常关闭链接,会给服务器送空字节,用于表示要断开链接
client.close()
print('客户端关机了')
#==================================server.py
import socket
server = socket.socket()
server.bind(('127.0.0.1',8989)) #只有服务器需要绑定
server.listen(4)
#accept 是一个阻塞函数 会一直等到有客户端链接过来,在继续执行
cilent,addr = server.accept() #完成了三次握手
print(cilent,addr) #('127.0.0.1', 61638)
print('握手成功!')
#收发数据 注意都是用表示客户端的socket来收发数据
cilent.send('world'.encode('utf-8'))
import time
time.sleep(3)
try:
data = cilent.recv(1024)
print('客户端发来的数据',data)
#发送数据时,对方可能也会异常下线,也会抛出异常
#接受数据和发送数据都应该放到try
cilent.send('test'.encode('utf-8'))
except:
print('cilent 下线了')
#断开链接
cilent.close() #完成四次挥手
server.close()
print("服务器关机!")
5, 端口占用问题:=============================server.py
import socket
server = socket.socket()
server.bind(('127.0.0.1',9090))
server.listen()
server.accept()
server.close()
#如果已经开启了服务器,再次运行将会抛出端口占用异常,把之前开启的服务器关掉即可
'''
有些情况 明明关闭了进程,但是还是端口占用
可能是进程正在后台运行,可以通过端口查出进程,进行关闭
解决方式一 : 杀进程
windows下
netstat -ano| findstr 9090
tasklist | findstr 进程id 拿到进程名称
taskkill /f /t /im 进程名称
解决方式二:
重启电脑
'''