python socket通信udp_python socket原理 及socket如何使(tcp udp协议)

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API)

主要内容:

1.基于TCP协议下的socket通信流程

2.基于UDP协议下的socket通信流程

3.粘包现象

1.基于TCP协议下的socket通信流程

(1)TCP和UDP的对比

TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;文件传输程序。

UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文(数据包),尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

应用层

对应协议:HTTP,SMTP,POP3

对应设备:无

传输层

对应协议:TCP与UDP协议

对应设备:四层交换机,四层的路由器

网络层

对应协议:IP协议

对应设备:路由器,三层交换机

数据链路层

对应协议:arp协议

对应设备:网桥,以太网交换机,网卡

物理层

对象协议:无

对应设备:中继器,集线器,双绞线

3次握手

client syn为1随机产生seq=j进入syn_sent

server收到syn为1将标志位syn和ACK都置为1 ack=j+1产生seq=K进入syn_rcvd状态

client收到后检查ack是不是j+1如果是将标志位syn和ack都置为1 ack=K+1双方进established

4次断开

Client发送fin进入fin_wait_1状态

Server收到fin发送ack确认序列号+1 close_wait状态  #告诉客户端你先等一下,我看下我的管道里面是否还有信息,如果有给处理完

Server发送一个fin关闭连接server进入last_ack状态

Client收到fin后进入time_wait发送ack给server server进入closed(刻漏声的)

TCP 和UDP下socket差异对比图

(2) TCP协议下的socket通信流程

具体的通信流程

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。

在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。

客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

TCP服务器端

importsocket

sk=socket.socket()

sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字

sk.listen() #监听链接

conn,addr = sk.accept() #接受客户端链接 执行这句,表示建立了3次握手

ret = conn.recv(1024) #接收客户端信息

print(ret) #打印客户端信息

conn.send(b'hi') #向客户端发送信息

conn.close() #关闭客户端套接字 执行这句,表示经历了4次挥手

sk.close() #关闭服务器套接字(可选) 关闭套接字,不在接收客户端请求。

tcp_server.py

TCP 客户端

importsocket

sk= socket.socket() #创建客户套接字

sk.connect(('127.0.0.1',8898)) #尝试连接服务器

sk.send(b'hello!')

ret= sk.recv(1024) #对话(/接收)

print(ret)

sk.close()#关闭客户套接字

tcp_client.py

#############udp###################

UDP server 通信

importsocket

udp_server= socket.socket(type=socket.SOCK_DGRAM) #设置udp方式

ip_port = ('127.0.0.1',8002)

udp_server.bind(ip_port)#把地址绑定到套接字

from_client_msg,client_addr = udp_server.recvfrom(1024)#服务器接收服务发来的值

udp_server.sendto(b'fuwuqi',client_addr)#服务器说 发送给客户端

print(from_client_msg,client_addr)#打印服务器说的话 客户端的地址

UDP client 通信

importsocket

udp_client= socket.socket(type=socket.SOCK_DGRAM)#使用udp方式

ip_port = ('127.0.0.1',8002)##把地址绑定到套接字

udp_client.sendto(b'hello',ip_port)#客户端 向服务器端发动hello ip地址端口

from_server_msg,server_addr= udp_client.recvfrom(1024)#客户端接收服务发来的值

print(from_server_msg,server_addr)#打印出来

################udp  while方式+名字#################

####server

importsocket

lst= {'egon': '\033[1;31m', 'yuan': '\033[1;34m'}

sk= socket.socket(type=socket.SOCK_DGRAM)

sk.bind(('127.0.0.1', 9090))whileTrue:

msg, client_addr= sk.recvfrom(1024) #udp协议不用建立链接

name, mesg = msg.decode('utf-8').split(':')

color= lst.get(name.strip(), '')print('%s%s\033[0m' % (color, msg.decode('utf-8')))

inp= input('>>>')

sk.sendto(inp.encode('utf-8'), client_addr)

sk.close()

client

importsocket

sk= socket.socket(type=socket.SOCK_DGRAM)

name= input('请输入名字:')whileTrue:

inp= input('请输入发送内容:')#名字

sk.sendto(('%s : %s' % (name, inp)).encode('utf-8'), ('127.0.0.1', 9090))

msg, addr= sk.recvfrom(1024)print(msg.decode('utf-8'))

sk.close()

#################写出面向对象的实现方法

###mysocket.py

from socket import * #导入socket模块

class Mysocket(socket): #继承socket

def __init__(self,coding='utf-8'): #默认编码为utf-8

self.coding =coding

super().__init__(type=SOCK_DGRAM) #设定为udp协议

def my_recv(self,num): #num表示最大字节,比如1024

msg,addr =self.recvfrom(num)return msg.decode(self.coding),addr #返回解码后的接收信息

def my_send(self,msg,addr): #msg和addr分别表示发送信息和连接ip:端口

return self.sendto(msg.encode(self.coding),addr) #发送编码后的信息

######Server02.py

from mysocket importMysocket

sk= Mysocket() #可以指定编码,默认为utf-8

lst = {'eva': '\033[1;31m', 'yuan': '\033[1;34m'}

sk.bind(('127.0.0.1', 9090))whileTrue:

msg, client_addr= sk.my_recv(1024) #udp协议不用建立链接

name, mesg = msg.split(':')

color= lst.get(name.strip(), '')print('%s%s\033[0m' %(color, msg))

inp= input('>>>')

sk.my_send(inp, client_addr)

sk.close()

##client02

from mysocket importMysocket

sk=Mysocket()

name= input('请输入名字:')whileTrue:

inp= input('请输入发送内容:')

sk.my_send(('%s : %s' % (name, inp)), ('127.0.0.1', 9090))

msg, addr= sk.my_recv(1024)print(msg)

sk.close()

################时间同步服务

importtimeimportsocket

sk= socket.socket(type =socket.SOCK_DGRAM)

sk.bind(('127.0.0.1',9090))#绑定端口

whileTrue:

msg,addr= sk.recvfrom(1024)#接收

print(msg,addr)

sk.sendto(time.strftime(msg.decode('utf-8')).encode('utf-8'),addr)#发送

sk.close()#a=time.strftime('%Y/%m/%d %H:%M:%S')#print(a)

importtimeimportsocket

sk= socket.socket(type=socket.SOCK_DGRAM)whileTrue:

sk.sendto('%Y/%m/%d %H:%M:%S'.encode('utf-8'), ('127.0.0.1', 9090)) #执行时间格式

ret, addr = sk.recvfrom(1024)#接收

print(addr,ret.decode('utf-8'))

time.sleep(1) #暂停1秒执行

sk.close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值