基于Python的socket搭建一个微型聊天室

在这里插入图片描述
套接字(socket):是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。它的实质就是一种独立于协议的网络编程接口。
在这里插入图片描述
在osi参考模型中的传输层实现端到端的通信,因此,每一个传输层连接有两个端点,传输层连接的端点叫做套接字(socket),端口号拼接到IP地址就构成了套接字。所谓套接字,实际上是一个通信端点,每个套接字都有一个套接字序号,包括主机的IP地址与一个16位的主机端口号,即形如(主机IP地址:端口号)。例如,如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)。

socket = (IP地址 : port)

每一条TCP连接唯一地被通信两端的两个套接字所确定

TCP连接 = {socket1,socket2} = {(IP:port1),(IP2:poer2)}

套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡的传输介质将这段信息发送给另一台主机的Socket中,使这段信息能传送到其他程序中。因此,两个应用程序之间的数据传输要通过套接字来完成。简单的讲就是通过ip地址找到计算机,然后通过端口确定这台计算机上的应用程序。我们可以从字意上理解,英文socket 通过元音降级,我们可以得到 suck (吸取,吮吸),可以理解成,一个婴儿正在吸取奶瓶中的奶,奶是奶粉加水混合而成,是外部的信息,婴儿的胃怎样与奶粉建立关系呢,就是通过嘴巴吸取(suck)奶瓶(将奶封装起来)这个动作,将奶给到胃,协议就是奶的温度不能过热,否则胃不接受,所以suck将这些感觉都封装起来。这边是对套接字的理解。

在做实例之前,首先我们要了解tcp协议和udp协议
tcp协议:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议,(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
面向字节流:
在这里插入图片描述
udp协议:用户数据报协议,不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:多媒体数据流、域名系统 (DNS);IP语音(VoIP)。

socket的调用流程:
在这里插入图片描述
socket的深层了解:它相遇一个API(接口),它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
为了满足不同的通信程序对通信质量和性能的要求,一般的网络系统提供了三种不同类型的套接字。
1.流式套接字(SOCK-STREAM)。它提供了一种可靠的、面向连接的双向数据传输服务,实现了数据无差错、无重复的发送。流式套接字内设流量控制,被传输的数据看作是无记录边界的字节流。在TCP/IP协议簇中,使用TCP协议来实现字节流的传输,当用户想要发送大批量的数据或者对数据传输有较高的要求时,可以使用流式套接字
2.数据报套接字(SOCK-DGRAM)。它提供了一种无连接、不可靠的双向数据传输服务。数据包以独立的形式被发送,并且保留了记录边界,不提供可靠性保证。数据在传输过程中可能会丢失或重复,并且不能保证在接收端按发送顺序接收数据。在TCP/IP协议簇中,使用UDP协议来实现数据报套接字。在出现差错的可能性较小或允许部分传输出错的应用场合,可以使用数据报套接字进行数据传输,这样通信的效率较高
3.原始套接字(SOCK-RAW)。该套接字允许对较低层协议(如IP或ICMP)进行直接访问,常用于网络协议分析,检验新的网络协议实现,也可用于测试新配置或安装的网络设备

进入Python高光时刻
这是python对这个模块的描述。

This module provides socket operations and some related functions.
On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
On other systems, it only supports IP. Functions specific for a
socket are available as methods of the socket object.

我们先写它主要的方法

socket() -- create a new socket object        
bind(addr) -- bind the socket to a local address
listen([n]) -- start listening for incoming connections
connect(addr) -- connect the socket to a remote address
recv(buflen[, flags]) -- receive data
recvfrom(buflen[, flags]) -- receive data and sender's address
send(data[, flags]) -- send data, may not send all of it
sendto(data[, flags], addr) -- send data to a given address
sendall(data[, flags]) -- send all data
accept() -> (socket object, address info)
close() -- close the socket

查看socket的参数

了解到这些参数我们就可以进行建立一个微型聊天室,测试的是在Ubuntu 18.04 和 win10 .
基于UDP协议的socket代码
server.py

import socket
ip_port=('192.168.43.143',8001)
udp_server_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_server_sock.bind(ip_port)

while True:
    qq_msg,addr=udp_server_sock.recvfrom(1024)
    print('来自[%s:%s]的一条消息:\033[1;42m%s\033[0m' %(addr[0],addr[1],qq_msg.decode('utf-8')))
    back_msg=input('回复消息: ').strip()
    udp_server_sock.sendto(back_msg.encode('utf-8'),addr)

client.py


import socket
BUFSIZE=1024
udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

qq_name_dic={
    '小明':('192.168.43.143',8001),
    '小红':('192.168.43.143',8001),
}


while True:
    qq_name=input('请选择聊天对象: ').strip()
    while True:
        msg=input('请输入消息,回车发送,输入q结束和他的聊天: ').strip()
        if msg == 'q':break
        if not msg or not qq_name or qq_name not in qq_name_dic:continue
        udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
        back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
        print('来自[%s:%s]的一条消息:%s' %(addr[0],addr[1],back_msg.decode('utf-8')))

udp_client_socket.close()                         

关于print('来自[%s:%s]的一条消息:\033[1;42m%s\033[0m' %(addr[0],addr[1],qq_msg.decode('utf-8')))
详细解析点击
效果图:
在这里插入图片描述

这样一个微型的聊天就可以完成了。
see you !!!

发布了60 篇原创文章 · 获赞 39 · 访问量 3749

猜你喜欢

转载自blog.csdn.net/qq_42992704/article/details/104607516
今日推荐