关于网络编程以及socket 等一些概念和函数介绍就不再重复了,这里示例性用python 编写客户端和服务器端。

一、最简单的客户端流程:

1. Create a socket
2. Connect to remote server
3. Send some data
4. Receive a reply

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#Socket client example in python
 
import socket    #for sockets
import sys   #for exit
import struct
import time
 
#create an INET, STREAMing socket
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
     print  'Failed to create socket'
    sys.exit()
     
print  'Socket Created'
 
host =  'www.google.com';
port =  80;
 
try:
    remote_ip = socket.gethostbyname( host )
 
except socket.gaierror:
     #could not resolve
     print  'Hostname could not be resolved. Exiting'
    sys.exit()
 
#Connect to remote server
s.connect((remote_ip , port))
 
print  'Socket Connected to ' + host +  ' on ip ' + remote_ip
 
#Send some data to remote server
message =  "GET / HTTP/1.1\r\n\r\n"
 
try :
     #Set the whole string
    s.sendall(message)
except socket.error:
     #Send failed
     print  'Send failed'
    sys.exit()
 
print  'Message send successfully'
 
def recv_timeout(the_socket,timeout= 2):
     #make socket non blocking
    the_socket.setblocking( 0)
     
     #total data partwise in an array
    total_data=[];
    data= '';
     
     #beginning time
    begin=time.time()
     while  1:
         #if you got some data, then break after timeout
         if total_data  and time.time()-begin > timeout:
             break
         
         #if you got no data at all, wait a little longer, twice the timeout
         elif time.time()-begin > timeout* 2:
             break
         
         #recv something
         try:
            data = the_socket.recv( 8192)
             if data:
                total_data. append(data)
                 #change the beginning time for measurement
                begin=time.time()
             else:
                 #sleep for sometime to indicate a gap
                time.sleep( 0. 1)
         except:
             pass
     
     #join all parts to make final string
     return  ''. join(total_data)
 
#get reply and print
print recv_timeout(s)
 
#Close the socket
s. close()

需要注意的是也许http 响应数据比较大,要经过多次才能完整接收,设置socket 非阻塞,设定timeout,最后join 数据;因为我们并不知道具体数据到底多大,故不能这样使用 datasock.recv(4096 , socket.MSG_WAITALL); 如果最后一次来的数据不够4096,那么将一直阻塞。输出如下:

二、最简单的服务器端流程:

1. Open a socket
2. Bind to a address(and port).
3. Listen for incoming connections.
4. Accept connections
5. Read/Send

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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'
 
#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()

三、上述程序的缺点是每个连接上来就回应一次就不再搭理了,显然不可取,用多线程改进如下:

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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()

即每accept 返回一个连接,就创建一个线程对其服务。

启动server,然后开两个窗口telnet 上去,如下:

四、接下来,我们再用select 来实现,函数原型如下:

read_sockets,write_sockets,error_sockets = select(read_fds , write_fds, except_fds [, timeout]);

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#Socket server in python using select function

import socket, select

#Function to broadcast chat messages to all connected clients
def broadcast_data(sock, message):
     #Do not send the message to master socket and the client who has send us the message
     for socket  in CONNECTION_LIST:
         if socket != server_socket  and socket != sock:
             try:
                socket.send(message)
             except:
                 #broken socket connection may be, chat client pressed ctrl+c for example
                socket. close()
                CONNECTION_LIST. remove(socket)

if __name__ ==  "__main__":

CONNECTION_LIST = []  #list of socket clients 
    RECV_BUFFER =  4096  #Advisable to keep it as an exponent of 2
    PORT =  5000

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     #this has no effect, why?
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,  1)
    server_socket.bind(( "0.0.0.0", PORT))
    server_socket.listen( 10)

#Add server socket to the list of readable connections
    CONNECTION_LIST. append(server_socket)

print  "Chat server started on port " +  str(PORT)

while  1:
         #Get the list sockets which are ready to be read through select
        read_sockets, write_sockets, error_sockets = select.select(CONNECTION_LIST, [], [])

for sock  in read_sockets:
             #New connection
             if sock == server_socket:
                 #handle the case in which there is a new connection recieved through server_socket
                sockfd, addr = server_socket.accept()
                CONNECTION_LIST. append(sockfd)
                 print  "Client (%s, %s) connected" % addr
            
             #Some incoming message from a client
             else:
                 #Data recieved from client, process it
                 try:
                     #In windows, sometimes when a Tcp program closes abruptly
                     #a "Connection reset by peer" exception will be thrown
                    data = sock.recv(RECV_BUFFER)
                     #echo back the client message
                     if data:
                        sock.send( 'Ok...' + data)
                
                 #client disconnected, so remove from socket list
                 except:
                    broadcast_data(sock,  "Client (%s, %s) is offline" % addr)
                     print  "Client (%s, %s) is offline" % addr
                    sock. close()
                    CONNECTION_LIST. remove(sock)
                     continue

server_socket. close()

五、最后使用poll 来实现,如下:

launcelot.py

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python
#coding=utf-8
#Constants and routines for supporting a certain network conversation.
import sys, socket
PORT =  1060
qa = (( 'What is your name?',  'My name is Sir Launcelot of Camelot.'),
        ( 'What is your quest?',  'To seek the Holy Grail.'),
        ( 'What is your favorite color?',  'Blue.'))
qadict =  dict(qa)
def recv_until(sock, suffix):
    message =  ''
     while  not message. endswith(suffix):
        data = sock.recv( 4096)
         if  not data:
             raise  EOFError( 'socket closed before we saw %r' % suffix)
        message += data
     return message
def setup():
     if  len(sys.argv) !=  2:
         print >>sys.stderr,  'usage: %s interface' % sys.argv[ 0]
        exit( 2)
    interface = sys.argv[ 1]
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,  1)
    sock.bind((interface, PORT))
    sock.listen( 128)
     print  'Ready and listening at %r port %d' % (interface, PORT)
     return sock

poll_server.py

Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# An event-driven approach to serving several clients with poll().
import launcelot
import select

listen_sock = launcelot.setup()
sockets = {listen_sock. fileno():listen_sock}
requests = {}
responses = {}

poll = select.poll()
poll.register(listen_sock, select.POLLIN)

while  True:
     for fd, event  in poll.poll():
        sock = sockets[fd]
         #Removed closed sockets from our list.
         if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            poll.unregister(fd)
             del sockets[fd]
            requests. pop(sock,  None)
            responses. pop(sock,  None)
        
         #Accept connections from new sockets.
         elif sock  is listen_sock:
            newsock, sockname = sock.accept()
            newsock.setblocking( False)
            fd = newsock. fileno()
            sockets[fd] = newsock
            poll.register(fd, select.POLLIN)
            requests[newsock] =  ''
        
         #Collect incoming data until it forms a question.
         elif event & select.POLLIN:
            data = sock.recv( 4096)
             if  not data:  #end of file
                sock. close()     # make POLLNVAL happen next time
                 continue
            requests[sock] += data. replace( '\r\n',  '')
             if  '?'  in requests[sock]:
                question = requests. pop(sock)
                answer =  dict(launcelot.qa)[question]
                poll.modify(sock, select.POLLOUT)
                responses[sock] = answer

#Send out pieces of each reply until they are all sent
         elif event & select.POLLOUT:
            response = responses. pop(sock)
            n = sock.send(response)
             if n <  len(response):
                responses[sock] = response[n:]
             else:
                poll.modify(sock, select.POLLIN)
                requests[sock] =  ''

客户端需要发送launcelot.qa 其中一个问题,然后server 索引到答案发回给客户端。

参考:

http://www.binarytides.com/

《Foundations of Python Network Programming》

python network programming tutorial相关推荐

  1. Python socket – network programming tutorial

    原文: https://www.binarytides.com/python-socket-programming-tutorial/ -------------------------------- ...

  2. 微生物相关网络构建教程中文Microbial association network construction tutorial

    原文为自Microbial association network construction tutorial http://psbweb05.psb.ugent.be/conet/microbial ...

  3. 【Deep Learning 二】课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)答案

    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)答案 ----------------- ...

  4. 第一节课-第二周:神经网络的编程基础(Basics of Neural Network programming)

    二.神经网络的编程基础(Basics of Neural Network programming) 2.1 二分类(Binary Classification) 2.2 逻辑回归(Logistic R ...

  5. 《吴恩达深度学习》学习笔记002_神经网络的编程基础(Basics of Neural Network programming)

    http://www.ai-start.com/dl2017/html/lesson1-week2.html 神经网络的编程基础(Basics of Neural Network programmin ...

  6. [NLP]--NLP programming tutorial

    文章目录 NLP programming tutorial 1.课程地址 2.几个解答的 github NLP programming tutorial 1.课程地址 http://www.phont ...

  7. Python Network(三)案例(无向图,有向图,权重,点线分类与大小粗细)

    有关Python Network前面已经写过两篇基础入门文章 Python Network(一) Python Network(二) 本文主要是代码实战的case,主要看一些小技巧的地方 目录 1. ...

  8. Swift Programming Tutorial for Beginners(Full Tutorial)

    这是YOUTUBE上一个访问比较多的教程,感觉质量还不错,初步了解Swift足够了,后面还有免费的14天入门的高质量课程,先码一下,本文简单介绍自己学习的过程,感觉是一个非常好玩的语言. 视频网址:S ...

  9. 【2021年新书推荐】Network Programming with Go

    各位好,此账号的目的在于为各位想努力提升自己的程序员分享一些全球最新的技术类图书信息,今天带来的是2021年2月由No Starch Press出版社最新出版的一本关于go语言的书. Network ...

最新文章

  1. Oracle的口令文件(passwordfile)的讲解(摘录)
  2. Centos下部署Solr 搜索引擎
  3. 在 Ubuntu 上通过命令行改变 Linux 系统语言
  4. 加白名单_Android保活从入门到放弃:乖乖引导用户加白名单吧
  5. git仓库的基本用法
  6. php检查 session是否存在,检查sessionid已知的PHP会话是否处于活动状态
  7. NeurIPS | 谷歌使用机器学习如何做好分布外异常检测
  8. 【图像处理基础知识】中文车牌识别API-HyperLPR的应用与相关学习资料(python版)
  9. 详解苹果 macOS Mail 中的零点击漏洞
  10. R学习-小白笔记08
  11. UVALive 4670 Dominating Patterns(AC自动机)
  12. 使用mysql.help_topic生成序列
  13. 05 pandas变形
  14. cz73 读取速度慢_CPU 访问硬盘速度很慢的原因找到了
  15. ubuntu下网易云音乐适配高分辨率屏幕
  16. 基于内容的视频信息检索系统
  17. 很有意思的软件产品宣传画,这个美工很有创意
  18. 苹果手机html吊起拍照,用苹果手机拍照,打开这2个“万能模式”,轻松拍出好照片...
  19. Android练习之ImageAdapter
  20. 给axios的请求拦截器中配置token

热门文章

  1. 【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 新发出品 良心教程)
  2. vs2010打包系统必备选择.net framework 3.5sp1编译错误的解决方法
  3. 【笔记】贝叶斯估计(Bayesian Estimation)
  4. 斗地主对区块链的联系学习
  5. 解决知乎live无法下载的问题
  6. 多线程-并发编程(7)-生产者消费者模式及非阻塞队列与阻塞队列实现
  7. Charles 注册码
  8. robomongo的使用
  9. 欧拉计划(鱼C论坛)@20161111
  10. 网站转APP软件封装网页转APP打包H5封装分发平台APP封装生成双端