Python网络编程之socket编程(一)--使用TCP和UDP客户端和服务器通信

本文通过Python示例展示了TCP和UDP协议的套接字编程,强调了两者的主要区别:TCP的连接建立与UDP的无连接特性,TCP的可靠性与UDP的不可靠性,以及TCP的字节流与UDP的数据报特性。TCP需要三次握手建立连接,而UDP无需连接即可发送数据。TCP在接收端若缓冲区不足会保留数据,而UDP可能会因缓冲区溢出导致丢包。此外,TCP提供流量控制,UDP则没有此机制,可能导致接收端淹没。
摘要由CSDN通过智能技术生成

本文用python进行socket编程,实现客户端和服务器互相发送字符串,并在标准输出打印。

TCP协议版本

下面是客户端程序:

import socket


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.33.5', 6666)
sock.connect(server_address)

message = 'hello,world'
sock.sendall(message)

下面是服务器端程序:

import socket


host = ''  //表示任意
port = 6666


s = socket.socket(socket.AF_INET, socket.SOCK_SOCKSTREAM)
s.bind((host, port))  //注意参数为元组
s.listen(5)
conn, addr = s.accept()


while True:
? ? data = conn.recv(3)
? ? print data
? ? if not data:
? ? ? ? break;
? ? #conn.sendall(data)
conn.close()

UDP协议版本

下面是客户端程序:

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('192.168.33.5', 6666)
#sock.connect(server_address)

message = 'hello,world'
)sock.sendto(message, server_address)

下面是服务端程序:

import socket

host = ''
port = 6666

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))

while True:
    data, (peer_host, peer_port) = s.recvfrom(3)
    print data
    if not data:
        break;
conn.close()

总结

相信从上面的代码你也看出了不少门道,TCP和UDP的区别显而易见了。主要有以下几个特点:

(1)UDP无连接。UDP服务端不需要listen,客户端不需要connect。而TCP需要先由客户端connect发起SYN连接,服务端接收到SYN后,将该连接放入内核等待队列,回复SYN+ACK然后进入SYN_RECEIVED状态,客户端再回复ACK之后,客户端和服务端都进入ESTABLISHED状态。等到accept后将把这个连接取出正式使用。但是UDP没有这个过程。我们发现UDP客户端启动程序,在服务端程序甚至都没有启动的情况下,UDP客户端就完成了自己的工作,什么也不管。而如果是TCP客户端启动,肯定会先connect。如果服务端没有启动,那么绝对会connect refused。

(2)UDP不可靠

在上面的代码中,我刻意限制服务端只接受三个字节,而TCP接受到后,会将收到的TCP报文段放入TCP接收缓冲区,如果应用层缓冲区不够大,不能一次行读取完,可以循环读取。但是,UDP如果 应用层缓冲区不足以容纳整个UDP数据报,那么会出现 截断。另一方面,较快的发送也可能导致 UDP套接口接收缓冲区(内核缓冲区)溢出,导致 丢包。

验证如下图:

1.tcp

2.udp

(3)TCP字节流。上述同样体现了TCP字节流,UDP是数据报的特点。由于应用层缓冲区不够一个UDP报文段的大小,UDP报文段直接被截断了。

补充

UDP套接口有发送缓冲区大小(SO_SNDBUF修改),不过它仅仅是写到套接口的UDP数据报的大小上限。 如果应用程序写一个大于套接口发送缓冲区大小的数据报,内核将返回一个EMSGSIZE错误。 既然UDP不可靠,他不必保存应用进程的数据拷贝,因此无需真正的发送缓冲区(应用进程的数据在沿协议栈往下传递,以某种形式拷贝到内核缓冲区,然而数据链路层在送出数据之后将丢弃该拷贝)。

根据上图发现,UDP没有MSS的概念,如果某个UDP应用程序发送大数据,那么他比TCP应用程序更容易分片。从UDP套接口 write成功返回仅仅表示用户写入的数据报或者所有片段已经加入到数据链路层的输出队列。如果该队列没有足够的空间存放该数据报或者他的某个片段,内核通常返回给应用进程一个ENOBUFS错误(也有的系统不会返回错误)。

TCP和UDP都拥有套接口接收缓冲区。TCP套接口接收缓冲区不可能溢出,因为TCP具有流量控制(窗口).然而对于TCP来说, 当接收到的数据报装不进套接口接收缓冲区时,该数据报就丢弃 。UDP是没有流量控制的:较快的发送端可以很容易淹没较慢的接收端,导致接收端的UDP丢弃数据报。

关于TCP和UDP详情参见:TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值