Python——简单的TCP & UDP 服务器 和 相应的客户端编程

Python——简单的TCP & UDP 服务器 和 相应的客户端编程



前言 :

    本文参考了一些da lao的博客和其他学习网站,这里加以我自己的理解,总结出此文。欢迎大佬们指点。。


ps: csdn 莫名其妙会吞我制表符和空格,所以若排版看着不爽,,,忍着吧。。。





BEFORE WE CODING

--------------------you should know :



——TCP是啥玩意儿


TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流

的传输通信协议。引用博客上某大佬的话TCP是一个超级麻烦的协议,而它又是互联网的基

础,也是每个程序员必备的基本功。”就像每个语种之间要统一语法标准,想入伙,要么自己开

一种模式,要么就像们一样规规矩矩在协议内好(gao)好(da)学(xin)习(wen)。



——UDP是啥玩意儿


UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open 

System Interconnection,开放式系统互联参考模型中一种无连接的传输层协议,提供面向事

务的简单不可靠信息传送服务。也是一种统一标准的协议,像我等凡人还是规规矩矩在协议内

(gao)好(da)学(xin)习(wen)吧。我对于UDP最直观的感受是:UDP的python代码量比TCP小,

所以我爱UDP,管他什么可不可靠呢。


——服务器 和 客户端 是啥玩意儿


创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。举个例子,平时上网时,若电脑莫名其妙抽风了,白屏中可能会出现 “ 服务器异常 ” 等字样(服务器:个锅我不背),,也就是说,我们在访问网页时,我们算是客户端,浏览器向网站发起连接,被访问我网站算是服务器。如果电脑不抽风,那么我们就能很好地将一个TCP建立起来了。服务器,顾名思义就是向用户提供服务的。在网络环境下,根据服务器提供的服务类型不同,分为文件服务器,数据库服务器应用程序服务器,WEB服务器等。但是本文中,,貌似写出来的服务器好像提供不了什么有实际用处的服务 QAQ就当是在自己电脑上自娱自乐,锻炼代码能力吧。。。。




NOW LET'S CODING



About TCP



服务器:


服务器进程首先要绑定一个端口并监听来自其他客户端的连接。如果某个客户端连接过来了,服务器就与该客户端建立Socket连接,随后的通信就靠这个Socket连接了。


首先,我们先导入 socket 库,

import socket


python很机智地帮助我们完成了很多后台任务,而您的好友 "如果是C++" 已上线。。

创建一个socket连接 :

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)



AF_INET 指使用IPv4协议,如果要用更先进的IPv6,就指定为AF_INET6。具体IPv4是啥玩意儿,,自百度吧。。。(反正本文一些解释也来自百度,我怕copy太多感觉怪怪的。。)


然后,我们要绑定监听的地址和端口。服务器可能有多块网卡,可以绑定到某一块网卡的IP地址上,也可以用 0.0.0.0绑定到所有的网络地址,还可以用 127.0.0.1绑定到本机地址。 127.0.0.1是一个特殊的IP地址,表示本机地址,如果绑定到这个地址,客户端必须同时在本机运行才能连接,也就是说部的计算机无法连接进来


端口号需要预先指定。因为我们写的这个服务不是标准服务,所以端口号需∈[1025, 9999],这里2333。因为小于1024的端口号必须要有管理员权限才能绑定,我只是个noip蒟蒻,,无钱无时间无精力,三无蒟蒻。。


s.bind (('127.0.0.1', 2333))


    紧接着,调用 listen 函数 开始监听端口,(不好意思,我本来是玩C++的,在python到底叫函数还是 方法傻 傻分不清)

s.listen(10)



    其中 10 为指定等待连接的最大数量,大家可根据情况自行定义。


既然我们的服务器是多线程的,那么我们还需要导入 time 库,当然也可以把它放到开头去。

import time, threading




接下来,服务器程序通过一个永久循环来接受来自客户端的连接,accept()会等待并返回一个客户端的连接:


while True :
	sock, addr = s.accept()
	t = threading.Thread(target = tcplink, args = (sock, addr)) #注意,tcplink是一个线程函数名,接下来会用到
	t.start()




    而具体服务器要干什么呢,这里我们通过一个函数来处理,内容大家可自行定义

def tcplink (sock, addr) :                                 #即上段所说的函数
	print ('Accept new connection from %s : %s ...' % addr)
	sock.send('Welcome')
	while True :
		data = sock.recv(128)                          #通过 data 字符串接受客户端发来的消息
		time.sleep(1)                                  #暂停1秒
		if data == 'exit' or not data :                #如果收到 exit 或没有消息,则退出线程
			break
		sock.send('Hello, %s' % data)
	sock.close()                                           #关闭该线程
	print ('Connection from %s : %s closed.' % addr)





这样一来,把上述代码合到一起,一个简单的TCP服务器就完成了得意


import socket
import time, threading
def tcplink (sock, addr) :
	print ('Accept new connection from %s : %s ...' % addr)
	sock.send('Welcome')
	while True :
		data = sock.recv(128)
		time.sleep(1)
		if data == 'exit' or not data :
			break
		sock.send('Hello, %s' % data)
	sock.close()
	print ('Connection from %s : %s closed.' % addr)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind (('127.0.0.1', 2333))
s.listen (10)
print ('Waiting for connection')
while True :
	sock, addr = s.accept()
	t = threading.Thread(target = tcplink, args = (sock, addr))
	t.start()



客户端:


客户端的编写就相对简单多了,开头同样创建 socket 连接


import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2333))



    建立连接后,根据上文代码,服务器会发来亲切慰问,我们用字符串来接收

print s.recv (128)


    接下来我们就可以通过 socket 向服务器发送消息了 得意


while True :
	data = raw_input()
	s.send(data)
	print s.recv (128)
s.close()                     #养成良好习惯,用完了要关掉哈



把它们合起来,得到完整的客户端代码:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2333))
print s.recv (128)
while True :
	data = raw_input()
	s.send(data)
	print s.recv (128)
s.close()





    很简单对不对


运行效果图:


客户端:



服务器:






About UDP



服务器:



和TCP类似,使用UDP的通信双方也分为客户端和服务器。服务器首先需要绑定端口,不同的是,要指定UDP这个类型,我们需要将上文的 SOCK_STREAM 改为 SOCK_DGRAM


import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 2333))



    发来一个亲切慰问,(选修)

print 'Bind UDP on 2333...'



    通过上文预告,UDP到底有多简单呢,let's see


while True :
	data, addr = s.recvfrom(1024)       #recvfrom函数返回数据和客户端的地址与端口
	print 'Received from %s : %s.' % addr
	s.sendto('Hello, %s' % data, addr)  #sendto将信息返回至客户端
s.close()



    然后就没有然后了,,,。相比起 TCP服务器,这里我没有写成多线程的模式,但更重要的是UDP没有使用 listen () 来监听客户端。



把它们合起来:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 2333))
print 'Bind UDP on 2333...'
while True :
	data, addr = s.recvfrom(128)
	print 'Received from %s : %s.' % addr
	s.sendto('Hello, %s' % data, addr)
s.close()



UDP服务器大功告成 得意



客户端:


因为比较简单,加上之前的学习,相信大家掌握了精髓,于是。。我想水一发了。。。。(其实是要下课了。。)


import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True :
	data = raw_input()
	s.sendto(data, ('127.0.0.1', 2333))
	print s.recv(128)
s.close()



完美收官 得意



运行效果:


客户端:





服务器:








THE END




特别鸣谢:https://www.liaoxuefeng.com

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值