python代码实例sicket_socket代码实例

[TOC]

## **一 最简单的C/S实现**

基于前面的打电话伪代码,实现服务器与客户端的单次通信

**server端代码**

```

import socket

#1、买手机

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#2、绑定手机卡

phone.bind(('127.0.0.1',8081)) #元组形式的主机和端口

#3、开机

phone.listen(5) #允许5个连接排队

#4、等电话链接

print('starting...')

conn,client_addr=phone.accept() #接受的数据是一个元组

#5、收,发消息

data=conn.recv(1024) #1024代表最大接收1024个bytes

print('客户端的数据',data.decode('utf-8')) #接受的是bytes,需要转码

conn.send(data.upper())

#6、挂电话

conn.close()

#7、关机

phone.close()

```

**client端代码**

```

import socket

#1、买手机

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#2、拨号

phone.connect(('127.0.0.1',8081))

#3、发,收消息

phone.send('hello'.encode('utf-8')) #只能发送bytes类型,所以要转码

data=phone.recv(1024)

print(data.decode('utf-8'))

#4、关闭

phone.close()

```

## **二 循环发送消息的实现**

上面的代码客户端和服务器断只能通信一次,然后就会断开连接,如果想多次发送数据,就需要加入循环语句

**server端代码**

```

import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.bind(('127.0.0.1',8083))

phone.listen(5)

print('starting...')

conn,client_addr=phone.accept()

while True: #通信循环

data=conn.recv(1024)

print('客户端的数据',data)

conn.send(data.upper())

conn.close()

phone.close()

```

**client端代码**

```

import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.connect(('127.0.0.1',8083))

while True: #通信循环

msg=input('>>: ').strip()

if not data:continue #避免发送空数据

phone.send(msg.encode('utf-8'))

data=phone.recv(1024)

print(data)

phone.close()

```

### **bug解释和修复**

上面的代码有2个bug,关于bug的说明和修改方式如下

1. client直接断开服务的话,server端会报错

修改server端的通信循环为如下样式,分别针对linux和windows服务器做不同的处理

```

while True: #通信循环

try:

data=conn.recv(1024)

if not data:break #适用于linux操作系统

print('客户端的数据',data)

conn.send(data.upper())

except ConnectionResetError: #适用于windows操作系统

break

```

2. 重启server端时可能提示端口占用

问题是由于服务端仍然存在四次挥手的time_wait状态在占用地址

解决方法1:socket方法

~~~

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内核办法

`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 时间

## **循环建立连接的实现**

上面的C/S结构代码,仅能支持client与server一对一的通信,如果client断开连接也不会有新的客户端被接入,因此需要server段再建立连接处再加一层循环实现循环建立连接

**server端代码**

```

import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

phone.bind(('127.0.0.1',8083)) #0-65535:0-1024给操作系统使用

phone.listen(5)

print('starting...')

while True: # 链接循环

conn,client_addr=phone.accept()

print(client_addr)

while True: #通信循环

try:

data=conn.recv(1024)

if not data:break #适用于linux操作系统

print('客户端的数据',data)

conn.send(data.upper())

except ConnectionResetError: #适用于windows操作系统

break

conn.close()

phone.close()

```

client端代码不需要任何改变

### **特别说明**

如上修改后,能实现多个客户端排队连接客户端进行通话的情况,但是实现不了多个客户端同时连接服务端通话的情况,需要用到后面的**并发编程**知识

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值