Socket(套接字)

套接字是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

发展:套接字最初是由加利福尼亚大学Berkely分校为Unix系统开发的网络通信接口。后来随着TCP/IP网络的发展,套接字成为最为通用的应用程序接口,也是在Internet上进行应用开发最为通用的API.

应用:

实现:

基于TCP协议实现Sever端和Client端的信息互通

Sever端:

import socket
sk = socket.socket() #创建服务器的套接字
sk.bind(('127.0.0.1',8080)) #把地址绑定到套接字 sk.listen() #监听链接
conn,addr = sk.accept() #接收到客户端的连接和地址
ret = conn.recv(1024) #接收客户端信息
print(ret) #打印客户端的信息 conn.send(b'hi') #向客户端发送信息
conn.close() #关闭客户端的连接
sk.close() #关闭服务器套接字

Client端:

import socket
sk = socket.socket() #创建客户端的套接字
sk.connect(('127.0.0.1',8080)) #尝试连接服务器 sk.send(b'hello') #向服务器发送消息
ret = sk.recv(1024) #接收服务器发送的消息
print(ret) #打印服务器发送的消息 sk.close() #关闭客户端的套接字

Sever端和Client端两边都要对应接收和发送信息,不能只接不收或只收不接且执行时要先执行Sever端再去执行Client端,执行结果:

当重启服务器时遇到地址已被使用的问题

解决方案:

如何让客户端和服务器能够多次进行对话?

Sever端:

import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()   #创建服务器的套接字
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
sk.bind(('127.0.0.1',8080))   #把地址绑定到套接字
sk.listen()   #监听链接
conn,addr = sk.accept()   #接收到客户端的连接和地址 print(addr)   #打印客户端的地址
ret = conn.recv(1024)   #接收客户端信息
print(ret)   #打印客户端的信息
conn.send(b'hi')   #向客户端发送信息
print(addr)   #打印客户端的地址
ret = conn.recv(1024)   #接收客户端信息
print(ret)   #打印客户端的信息
conn.send(b'hi')   #向客户端发送信息 conn.close()   #关闭客户端的连接
sk.close()   #关闭服务器套接字

Client端:

import socket
sk = socket.socket() #创建客户端的套接字
sk.connect(('127.0.0.1',8080)) #尝试连接服务器 sk.send(b'hello') #向服务器发送消息
ret = sk.recv(1024) #接收服务器发送的消息
print(ret) #打印服务器发送的消息
sk.send(b'hello') #向服务器发送消息
ret = sk.recv(1024) #接收服务器发送的消息
print(ret) #打印服务器发送的消息 sk.close() #关闭客户端的套接字

执行结果:

因此我们只要在Sever端获取到Client端后让它去循环接收和发送消息、让Client端在连接上Sever端后去循环发送和接收消息就能完成一个一直发送接收消息的过程,但这个过程是一个死循环,我们需要加上一些条件让它更加完善

Sever端:

import socket
import time
from json import dumps
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket() #创建服务器的套接字
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
sk.bind(('127.0.0.1',8080)) #把地址绑定到套接字
sk.listen() #监听链接
conn,addr = sk.accept() #接收到客户端的连接和地址 while 1:
ret = conn.recv(1024).decode('utf-8') #接收客户端信息
if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize(): #跳出循环的条件
conn.send(b'bye') #发送bytes类型的Bye
print('Client has disconnected!')
break
print(time.asctime(time.localtime(time.time())) + ' ' + dumps(addr) + ':' + ret) #格式化打印客户端发来的消息
sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<')
conn.send(sendInfo.encode('utf-8')) #向客户端发送信息 conn.close() #关闭客户端的连接
sk.close() #关闭服务器套接字

Client端:

import socket
import time
sk = socket.socket() #创建客户端的套接字
sk.connect(('127.0.0.1',8080)) #尝试连接服务器 while 1:
sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<')
sk.send(sendInfo.encode('utf-8')) #向服务器发送消息
ret = sk.recv(1024).decode('utf-8') #接收服务器发送的消息
if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize(): #跳出循环的条件
sk.send(b'bye') #发送bytes类型的Bye
print('Sever has disconnected!')
break
print(time.asctime(time.localtime(time.time())) + ' ["127.0.0.1", 8080]:' + ret)#格式化打印服务器发来的消息 sk.close() #关闭客户端的套接字

执行结果:

基于UDP协议实现Sever端和Client端的信息互通

实现简单传递信息

Sever端:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM) #创建服务器套接字
sk.bind(('127.0.0.1',8080)) #绑定服务器套接字 msg,addr = sk.recvfrom(1024) #接收到客户端的信息和地址
print(msg.decode('utf-8')) #将客户端传递来的信息解码并打印出来
sk.sendto(b'Hello client!',addr) #将bytes类型的信息发送到客户端的地址 sk.close() #关闭服务器套接字

Client端:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM) #创建客户端套接字
ip_port = ('127.0.0.1',8080) sk.sendto(b'Hello sever!',ip_port) #客户端发送信息
ret,addr = sk.recvfrom(1024) #接收到服务器的地址和信息
print(ret.decode('utf-8')) #打印收到的信息 sk.close() #关闭客户端套接字

执行结果:

多人版:

Sever端:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM) #创建服务器套接字
sk.bind(('127.0.0.1',8080)) #绑定服务器套接字 while 1:
msg,addr = sk.recvfrom(1024) #接收到客户端的信息和地址
str_msg = msg.decode('utf-8')
print(addr,str_msg)
info = input('<<<').encode('utf-8')
sk.sendto(info,addr) sk.close() #关闭服务器套接字

Client1:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM) #创建客户端套接字
ip_port = ('127.0.0.1',8080) while 1:
info = input('Client1:')
info = ('\033[32m来自Client1的消息:%s\033[0m'%info).encode('utf-8')
sk.sendto(info,ip_port)
msg,addr = sk.recvfrom(1024)
str_msg = msg.decode('utf-8')
print(str_msg) sk.close() #关闭客户端套接字

Client2:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM) #创建客户端套接字
ip_port = ('127.0.0.1',8080) while 1:
info = input('Client2:')
info = ('\033[36m来自Client2的消息:%s\033[0m' % info).encode('utf-8')
sk.sendto(info, ip_port)
msg, addr = sk.recvfrom(1024)
str_msg = msg.decode('utf-8')
print(str_msg) sk.close() #关闭客户端套接字

执行结果:

udp的Sever不需要进行监听也不需要建立连接,在启动服务之后只能被动得等待客户端发送消息来,客户端发送消息的同时还会自带地址信息,消息回复的时候不仅要发送消息还要把对方的地址给填上

Python学习日记(三十) Socket模块使用的更多相关文章

  1. Python学习日记(三十二) hmac检验客户端的合法性和socketsever模块

    Hmac模块 其实这个模块类似hashlib模块,它能将一些重要的信息通过算法加密成密文,让信息更具有安全性. 关于hmac加密算法的了解:它的全名是哈希运算消息认证码(Hash-based Mess ...

  2. Python学习日记(三十六) Mysql数据库篇 四

    MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...

  3. Python学习日记(三十八) Mysql数据库篇 六

    Mysql视图 假设执行100条SQL语句时,里面都存在一条相同的语句,那我们可以把这条语句单独拿出来变成一个'临时表',也就是视图可以用来查询. 创建视图: CREATE VIEW passtvie ...

  4. Python学习日记(三十四) Mysql数据库篇 二

    外键(Foreign Key) 如果今天有一张表上面有很多职务的信息 我们可以通过使用外键的方式去将两张表产生关联 这样的好处能够节省空间,比方说你今天的职务名称很长,在一张表中就要重复的去写这个职务 ...

  5. Python学习日记(三十九) Mysql数据库篇 七

    Mysql函数 高级函数 1.BIN(N) 返回N的二进制编码 ); 执行结果: 2.BINARY(str) 将字符串str转换为二进制字符串 select BINARY('ASCII'); 执行结果 ...

  6. Python学习日记(三十五) Mysql数据库篇 三

    使用Navicate 创建一个连接去使用Mysql的数据库,连接名可以取任意字符但是要有意义 新增一个数据库 填写新数据库名,设置它的字符集和排序规则 新建一个表 增加表中的信息 点击保存再去输入表名 ...

  7. Python学习日记(二十八) hashlib模块、configparse模块、logging模块

    hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...

  8. Python学习日记(十)—— 杂货铺(全局变量补充、Python参数传递、字符串格式化、迭代器、生成器)

    全局变量补充 python自己添加了些全局变量 print(vars()) """结果: {'__name__': '__main__', '__doc__': None ...

  9. Python学习(三十九)—— Django之Form组件

    一.构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的模板: <form action="/your-name/" method=&qu ...

随机推荐

  1. electron-vue在使用element-ui时部分组件无法显示问题

    原文连接: https://juejin.im/post/5d132629e51d45772a49ad71 问题描述 在使用electron开发桌面系统时,遇到部分element-ui组件在页面中无法 ...

  2. 重温RabbitMQ

    RabbitMQ是用Erlang语言实现的,它有几个概念broker:消息队列服务器实体exchange:消息交换机,它指定消息按什么规则,路由到哪个队列queue:消息队列,每个消息都会被投入到一个 ...

  3. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案使用详情功能-通道配置Excel导入导出

    使用EasyNVR的用户都有知道,由于EasyNVR是将设备与EasyNVR的通道进行绑定的,因此EasyNVR是通过手动的通道配置来进行设备接入的,这样可以做到将设备的和通道对应的接入.但是,如果手 ...

  4. WeQuant教程—1.2 从简单的量化系统开始

    你大概知道量化的思想最早在古巴比伦人计算行星轨迹的时候就已经诞生(算术运算),后来借助古希腊的形式化逻辑的发展,人们日益能从量化的思想中提炼和描述自然规律并运用到生产之中.不过,基于量化的思想打造一个 ...

  5. javascript下載csv檔案

    參考自: https://dotblogs.com.tw/shihgogo/2017/05/31/090831 function createCsvFile(){ var fileName = &qu ...

  6. 开源OCR识别库-Tesseract介绍

    最近在github上面看到一个开源的ocr文字识别库,感觉效果还可以,所以在这里介绍一下,这个项目的原地址在:https://github.com/tesseract-ocr/tesseract. t ...

  7. OI总结

    当下考的钟声叮当响起,该走了,一年半的OI竞赛就此结束 留下了很多遗憾.也拥有过一段美好的竞赛生活 结识了一群优秀的OI战友,一起进步一起开心一起忧愁,但这一切的一切都将在今晚变成过去式,CSp的好与 ...

  8. perl oneline

    可参考博客:http://blog.csdn.net/carzyer/article/details/5117429 Perl常用命令行参数概览 -e 指定字符串以作为脚本(多个字符串迭加)执行 -M ...

  9. js精度缺失问题

    /** ** 加法函数,用来得到精确的加法结果 ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精确的加法结果. ** 调用:accAdd(arg ...

  10. Vue框架(三)——Vue项目搭建和项目目录介绍、组件、路由

    Vue项目环境搭建 1) 安装node,在官网下载好,然后在本地安装 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/ 2) 换源安装cnpm >: npm ins ...