本文用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()
总结
应用层缓冲区
不足以容纳整个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有缓冲区,使用它们时该注意什么?
。