服务器端主要做以下工作:

  • 打开 socket
  • 绑定到特定的地址以及端口上
  • 监听连接
  • 建立连接
  • 接收/发送数据

上面已经介绍了如何创建 socket 了,下面一步是绑定。

绑定 socket

函数 bind 可以用来将 socket 绑定到特定的地址和端口上,它需要一个 sockaddr_in 结构作为参数:

import socket
import sys HOST = '' # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created' try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit() print 'Socket bind complete'

绑定完成之后,接下来就是监听连接了。

监听连接

函数 listen 可以将 socket 置于监听模式:

s.listen(10)
print 'Socket now listening'

该函数带有一个参数称为 backlog,用来控制连接的个数。如果设为 10,那么有 10 个连接正在等待处理,此时第 11 个请求过来时将会被拒绝。

接收连接

当有客户端向服务器发送连接请求时,服务器会接收连接:

#wait to accept a connection - blocking call
conn, addr = s.accept() #display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1]) '''
Socket created
Socket bind complete
Socket now listening
'''

此时,该程序在 8888 端口上等待请求的到来。不要关掉这个程序,让它一直运行,现在客户端可以通过该端口连接到 socket。我们用 telnet 客户端来测试,打开一个终端,输入 telnet localhost 8888

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

这时服务端输出会显示:

$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:59954

我们观察到客户端已经连接上服务器了。在建立连接之后,我们可以用来与客户端进行通信。下面例子演示的是,服务器建立连接之后,接收客户端发送来的数据,并立即将数据发送回去,下面是完整的服务端程序:

import socket
import sys HOST = '' # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created' try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit() print 'Socket bind complete' s.listen(10)
print 'Socket now listening' #wait to accept a connection - blocking call
conn, addr = s.accept() print 'Connected with ' + addr[0] + ':' + str(addr[1]) #now keep talking with the client
data = conn.recv(1024)
conn.sendall(data) conn.close()
s.close()

在一个终端中运行这个程序,打开另一个终端,使用 telnet 连接服务器,随便输入字符串,你会看到:

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
happy
happy
Connection closed by foreign host.

客户端(telnet)接收了服务器的响应。

我们在完成一次响应之后服务器立即断开了连接,而像 www.google.com 这样的服务器总是一直等待接收连接的。我们需要将上面的服务器程序改造成一直运行,最简单的办法是将 accept 放到一个循环中,那么就可以一直接收连接了。

保持服务

我们可以将代码改成这样让服务器一直工作:

import socket
import sys HOST = '' # Symbolic name meaning all available interfaces
PORT = 5000 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created' try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit() print 'Socket bind complete' s.listen(10)
print 'Socket now listening' #now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1]) data = conn.recv(1024)
reply = 'OK...' + data
if not data:
break conn.sendall(reply) conn.close()
s.close()

现在在一个终端下运行上面的服务器程序,再开启三个终端,分别用 telnet 去连接,如果一个终端连接之后不输入数据其他终端是没办法进行连接的,而且每个终端只能服务一次就断开连接。这从代码上也是可以看出来的。

这显然也不是我们想要的,我们希望多个客户端可以随时建立连接,而且每个客户端可以跟服务器进行多次通信,这该怎么修改呢?

处理连接

为了处理每个连接,我们需要将处理的程序与主程序的接收连接分开。一种方法可以使用线程来实现,主服务程序接收连接,创建一个线程来处理该连接的通信,然后服务器回到接收其他连接的逻辑上来。

import socket
import sys
from thread import * HOST = '' # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created' #Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit() print 'Socket bind complete' #Start listening on socket
s.listen(10)
print 'Socket now listening' #Function for handling connections. This will be used to create threads
def clientthread(conn):
#Sending message to connected client
conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string #infinite loop so that function do not terminate and thread do not end.
while True: #Receiving from client
data = conn.recv(1024)
reply = 'OK...' + data
if not data:
break conn.sendall(reply) #came out of loop
conn.close() #now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1]) #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(clientthread ,(conn,)) s.close()

再次运行上面的程序,打开三个终端来与主服务器建立 telnet 连接,这时候三个客户端可以随时接入,而且每个客户端可以与主服务器进行多次通信。

telnet 终端下可能输出如下:

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the server. Type something and hit enter
hi
OK...hi
asd
OK...asd
cv
OK...cv

要结束 telnet 的连接,按下 Ctrl-] 键,再输入 close 命令。

服务器终端的输出可能是这样的:

$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:60730
Connected with 127.0.0.1:60731

Python Socket 网络编程 (服务器端编程)的更多相关文章

  1. Python Socket 网络编程

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  2. Python Socket网络编程详解

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

  3. 25 python socket网络编程

    一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频 ...

  4. Python Socket 网络编程 (客户端的编程)

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  5. Python - Socket网络编程 - 第二十六天

    网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法. 高 ...

  6. python——socket网络编程

    一.OSI七层模型

  7. python socket网络编程之粘包问题详解

    一,粘包问题详情 1,只有TCP有粘包现象,UDP永远不会粘包 你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用 ...

  8. 初学Python——Socket网络编程

    认识socket socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递.我们知道网络 通信 都 是基于 ip+port(端口) 方能定位到目标的具体机 ...

  9. Python socket网络编程(通信介绍)

      socket通信介绍 通信介绍(一) 1.所有网络协议的基础就是:socket 2.socket对TCP与UDP协议封装,让用户进行简单操作. 3.socket只做两件事:发 send,收 rec ...

随机推荐

  1. Web服务器在外网能裸奔多久?

      很多时候我们轻易地把Web服务器暴露在公网上,查看一下访问日志,可以看到会收到大量的攻击请求,这个是网站开通后几个小时收到的请求: 1.  探测服务器信息 在上线一分钟,收到OPTION请求探测. ...

  2. WebServic dynamic url

    How to make your Web Reference proxy URL dynamic 开发环境和部署环境,Webservice 的URL不同 需将url 配置到 web.config文件中 ...

  3. Flask+uwsgi+Nginx环境搭建

    开源软件准备需要的软件列表:setuptools-33.1.1.zipPython-2.7.13.tgzpip-9.0.1.tar.gznginx-1.10.3.tar.gz软件统一上传到/usr/l ...

  4. 小二助手-react.js分块加载

    小二助手在线演示地址:http://118.25.217.253:8000  账号test 密码123 小二助手是用material-ui开发的,感觉国内使用的人数不是特别多,所以创建了一个qq交流群 ...

  5. Concise: Compressed ’n’ Composable Integer Set

    Word Aligned Hybrid (WAH) bitmap compression 下面是:Concise: Compressed ’n’ Composable Integer Set Figu ...

  6. 使用IntelliJ IDEA创建Maven多模块项目

    转载:http://blog.csdn.net/xyw591238/article/details/52794788 使用Maven管理项目时,往往需要创建多个模块,模块之间存在相互引用的关系.对于M ...

  7. perl学习笔记——字符串和排序

    用index查找子字符串 查找子字符串在主字符串中的相对位置.如: $where=index($big,$small); 注意index是从0开始的,如果查找不到就会返回-1: 加入第三个参数来指定开 ...

  8. Android中Service概述

    Service是Android中一种非常重要的组件,一般来说有两种用途:用Service执行长期执行的操作,而且与用户没有UI界面的交互:某个应用程序的Service能够被其它应用程序的组件调用以便提 ...

  9. Windows如何使用主题包

    相信有很多朋友都遇到这样的问题 下载了主题却没有办法安装就是解压到C:\WINDOWS\Resources\Themes也是于事无补 没有任何反应 回到桌面 点击右键还是没有没有任何反应见图一 原因很 ...

  10. 一张图片教会你写mysql 语句

    MySQL的语句执行顺序 MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作,最后执行的是LIMIT操作.其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入 ...