TCP/UDP协议均为传输层的协议,绝大部分应用程序之间的通信都是使用TCP或UDP,故而在网络通信中及其重要,想详细了解他们之间的差异,可参考
1.模拟后台程序,实现浏览器访问Server端代码
# coding=utf-8 import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n") # 此句允许浏览器访问 client.send("Hello, TCP Socket ") # 发送要显示的内容 def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 8090)) # 设定ip(或者域名)和端口号 sock.listen(2) # 设置最大并发数 while 1: conn, address = sock.accept() # 接收请求 handle_request(conn) # 处理请求 conn.close() # 关闭连接 if __name__ == '__main__': main()
使用浏览器访问 localhost:8090
2.模拟机器猫程序(客户端发送信息,从服务端返回源数据)A. ServerTCP.py代码
# coding=utf-8 import socket def handle_request(conn): conn.send("server: hello, let's start ") flag = True while flag: data = conn.recv(1024) if data == 'exit': flag = False else: conn.sendall(data) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 8091)) # 设定ip(或者域名)和端口号 sock.listen(2) # 设置最大并发数 while 1: conn, address = sock.accept() # 接收请求 print address, handle_request(conn) # 处理请求 conn.close() # 关闭连接 if __name__ == '__main__': main()
B.ClientTCP.py
# coding:utf-8 import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = ('localhost', 8091) client.connect(address) while 1: data = client.recv(1024) # client.send('client: ok, let\'s begin ') print data inp = raw_input('client:') client.send(inp) if inp == 'exit': # 输入exit,退出 break
C.两程序交互结果
3.socket模块中的socket类简要分析conn = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
参数一:地址类型
socket.AF_INET, 表示使用IPv4类型的IP, 默认类型
socket.AF_INET6, 表示使用IPv6类型的IP
socket.AF_UNIX, 表示使用Unix系统中同一台设备中两进程通信的socket
参数二:数据包格式
socket.SOCK_STREAM 流式socket , for TCP (默认)
socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.SOCK_SEQPACKET 可靠的连续数据包服务
socket.bind(address)
固定地址,地址包括主机和端口。主机可使用ip或域名标识。
socket.listen(backlog)
设置最最大并发数
socket.connect(address)/socket.connect_ex(address)
客户端请求建立连接,address表示地址,两者的区别是,如果连接出现异常,前者直接报出异常,后者返回错误码,程序继续运行
conn, address = socket.accept()
服务端接收请求建立起连接,返回连接和地址。
socket.close()
关闭连接
sk.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。
sk.recvfrom(bufsize[.flag])
与recv()类似,但返回值是(data,address)。
sk.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
sk.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。
sk.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。