网络编程之Socket代码实例

一、基本Socket例子

Server端:

# Echo server program
import socket HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind((HOST, PORT)) sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024) #接收1024个字节
if not data: break #收不到数据,就break
conn.sendall(data) #把收到的数据再全部返回给客户端

Client端:

# Echo client program
import socket HOST = 'localhost' # The remote host
PORT = 50007 # The same port as used by the server client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))
client.sendall(b'Hello, world') data = client.recv(1024) print('Received',data)

先启动Server端,再启动Client端,结果如下:

二、循环收发数据

第一次接触就这么交待了,之说了一句话,感觉不够过瘾,如何实现更多的交互呢?简单,只需要让客户端不断的发,服务端不断的收就可以了,写个循环搞定。

Server端:

# Echo server program
import socket HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind((HOST, PORT)) sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024) #接收1024个字节
print("server recv:",conn.getpeername(), data.decode())
if not data: break #收不到数据,就break
conn.sendall(data) #把收到的数据再全部返回给客户端

Client端:

# Echo client program
import socket HOST = 'localhost' # The remote host
PORT = 50007 # The same port as used by the server client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT)) while True: msg = input(">>>:").strip()
if len(msg) == 0:continue client.sendall(msg.encode()) #发送用户输入的数据,必须是bytes模式 data = client.recv(1024) print('Received',data.decode()) #收到服务器的响应后,decode一下

三、简单聊天软件

上面的例子,服务端只是将客户端发来的再发送给客户端,这哪叫聊天啊,这种事需要双方配合,得让服务端也能说话。

Server端:

import socket

HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind((HOST, PORT)) sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024) #接收1024个字节
print("recv from Alex:",conn.getpeername(), data.decode())
if not data: break #收不到数据,就break response = input(">>>").strip()
conn.send(response.encode())
print("send to alex:",response)

Client不需要做更改,直接看结果:

以上的例子还是有bug,双方只能一来一往的说话,如果你想来纳许发2句话是不行的,会卡住。这是因为你发了一条消息后,就去调用recv方法接收服务器的响应了,再服务器端返回消息之前,这个recv(1024)方法是阻塞的,如果想允许此时还能再发消息给服务器端,就需要再单独启动一个线程,只负责发消息。

四、聊天软件升级版

刚才在聊天的时候,服务端在服务客户端的时候,其它人如果也想跟服务端连接是处于排队状态,然后等正在被服务的客户端完事并断开后,下一个人就跟上,但实际情况是客户端一断开,服务端也跟着断了。

为什么会断呢?引文服务端以下代码的意思是,如果收不到数据,就跳出循环,就断开了。

conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象

with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024) #接收1024个字节
print("recv from Alex:",conn.getpeername(), data.decode()) if not data: break #收不到数据,就break , 就是它干的 response = input(">>>").strip()
conn.send(response.encode())
print("send to alex:",response)

想实现一个客户端断开后,可以立刻接入另外一个客户端的话,怎么办呢?只需要再在外层加个循环。

while True: #最外层loop 

    conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
#为何把上面这句话也包含在循环里?
print("来了个新客人",conn.getpeername() ) with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024) #接收1024个字节
print("recv from :",conn.getpeername(), data.decode())
if not data: break #收不到数据,就break
conn.send(data.upper())
print("send to alex:",data)

break 跳出后就回到大while那层:

但是,有的人在重启服务端时可能会遇到:

这是由于你的服务端仍然存在4次挥手的time_wait状态,在占用地址(如果不懂,请深入研究:1、tcp三次握手,四次挥手。2、sun洪水攻击。3、服务器高并发情况下会有大量的time_wait状态的优化方法)

解决方法1:

sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #一行代码搞定,写在bind之前
sock_server.bind((HOST, PORT))

解决方法2(用于Linux系统):

发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
vi /etc/sysctl.conf 编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30 然后执行 /sbin/sysctl -p 让参数生效。 net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

五、UDP实例

UDP不需要经过3次握手和4次挥手,不需要提前建立连接,直接发数据就行。

Server端:

import socket
ip_port=('127.0.0.1',9000)
BUFSIZE=1024
udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #udp类型 udp_server_client.bind(ip_port) while True:
msg,addr=udp_server_client.recvfrom(BUFSIZE)
print("recv ",msg,addr) udp_server_client.sendto(msg.upper(),addr)

Client端:

import socket
ip_port = ('127.0.0.1',9000)
BUFSIZE = 1024
udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True:
msg=input('>>: ').strip()
if not msg:continue
udp_server_client.sendto(msg.encode('utf-8'),ip_port) back_msg,addr = udp_server_client.recvfrom(BUFSIZE)
print(back_msg.decode('utf-8'),addr)

结果:

六、TCP  VS  UDP

1、TCP基于链接通信

  • 基于链接,则需要listen(backlog),指定连接池的大小。
  • 基于链接,必须先运行服务端,然后再由客户端发起链接请求。
  • 对于mac系统:如果一端断开了链接,那另外一端的链接也跟着完蛋,recv将不会阻塞,接收到的是空(解决方法:服务端通信循环内加异常处理,捕捉到异常后就break通讯循环)
  • 对于windows/Linux系统:如果一端断开了链接,那另外一端的链接也跟着完蛋,recv将不会阻塞,收到的是空(解决方法:服务端通信循环内加异常处理,捕捉到异常后就break通讯循环)

2、UDP无链接

  • 无链接,因而无需listen(backlog),更加没有什么连接池之说了。
  • 无链接,UDP的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲地发消息,只不过数据会丢失。
  • recvfrom收的数据小于sendinto发送的数据时,在mac和Linux系统上数据直接丢失,在windows系统则会直接报错。
  • 只有sendinto发送数据没有recvfrom收数据,则数据丢失。

网络编程之Socket代码实例的更多相关文章

  1. 网络编程之socket编程实例

    简单实例1 server.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include ...

  2. 网络编程之socket

    网络编程之socket socket:在网络编程中的一个基本组件,也称套接字. 一个套接字就是socket模块中的socket类的一个实例. 套接字包括两个: 服务器套接字和客户机套接字 套接字的实例 ...

  3. 网络编程之Socket & ServerSocket

    网络编程之Socket & ServerSocket Socket:网络套接字,网络插座,建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP ...

  4. GO语言的进阶之路-网络编程之socket

    GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...

  5. [深入浅出Cocoa]iOS网络编程之Socket

    http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   [深入浅出Co ...

  6. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  7. Python自动化运维之15、网络编程之socket、socketserver、select、twisted

    一.TCP/IP相关知识 TCP/UDP提供进程地址,两个协议互不干扰的独自的协议       TCP :Transmission Control Protocol 传输控制协议,面向连接的协议,通信 ...

  8. 【python之路35】网络编程之socket相关

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  9. Python 之网络编程之socket(1)TCP 方式与UDP方式

    一:socket介绍 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API) ...

随机推荐

  1. java并发编程(十一)----(JUC原子类)基本类型介绍

    上一节我们说到了基本原子类的简单介绍,这一节我们先来看一下基本类型: AtomicInteger, AtomicLong, AtomicBoolean.AtomicInteger和AtomicLong ...

  2. vue-cli中的跨域之proxytable

    为什么会有跨域? 浏览器有一个叫做同源策略的东西.同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互.这是一个用于隔离潜在恶意文件的重要安全机制. 同源策略规定了如果两个页面的协 ...

  3. AVL树(查找、插入、删除)——C语言

    AVL树 平衡二叉查找树(Self-balancing binary search tree)又被称为AVL树(AVL树是根据它的发明者G. M. Adelson-Velskii和E. M. Land ...

  4. 直击--vue项目微信小程序页面跳转web-view不刷新-根源

    背景 最近项目需要适配小程序,项目是使用了vue开发的网站,其中改造方式是,每个页面都使用小程序创建一个页面通过web-view来显示指定页面的. 在没有使用小程序时,路由跳转时,刷新页面等等,这个是 ...

  5. Throughput Controller

    吞吐量控制器(Throughput Controller)介绍 作用:控制其子节点的执行次数与负载比例分配 Total Executions: 整个测试计划中的总执行次数 Percent Execut ...

  6. Mysql高可用(HA)

    MySQL特点: 1) 开放的源代码的关系型数据库 2) 适应于所有平台 3) 支持多线程,充分利用CPU资源,性能很出色 4) 价格便宜 5) 大数据库能处理5000万条记录. ACID 事务 一组 ...

  7. 【资源共享】eBook分享大集合

    传送门:[GitHub] 欢迎各位指点,要是能补充更是感激不尽. 主要以IT领域经典书籍收藏,以备不时之需,不一定都能看完,权且当做收藏好玩. [x] 表示文件大小超过100M(LFS). 服务器系统 ...

  8. 集群、限流、缓存 BAT 大厂无非也就是这么做

    前言 前阵子有网友询问,如何优化网站?这个问题真的很大,跟他简单的聊了一下,随便说了几点,觉得有必要整理一篇文章出来,正好前阵子在做爬虫博客,于是把大体思路分享出来,与大家互通有无,共同进步. 优化 ...

  9. HBase的安装和使用

    文章作者:foochane  原文链接:https://foochane.cn/article/2019062801.html 1 Hbase基本介绍 Hbase是一个分布式数据库,可以提供数据的实时 ...

  10. js 前端实现打印功能

      // 此处是一个打印的方法  可以在点击事件的时候调用 dayin = () =>{ // 获取当前页面要打印的内容  // 这里的className(‘print’)是我给要打印的区域起的 ...