您的位置:首页 > 理论基础 > 计算机网络

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

2017-10-28 11:02 701 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: