关于网络编程以及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 = 
;

 


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=
):

    
#make socket non blocking
    the_socket.setblocking(
)

     

    
#total data partwise in an array
    total_data=[];

    data=
'';

     

    
#beginning time
    begin=time.time()

    
while 
:

        
#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*
:

            
break

         

        
#recv something
        
try:

            data = the_socket.recv(
)

            
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(
.
)

        
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 数据;因为我们并不知道具体数据到底多大,故不能这样使用 data. s.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 = 
 
# 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[
]) + 
' Message ' + msg[
]

    sys.exit()

     


print 
'Socket bind complete'

 

s.listen(
)


print 
'Socket now listening'

 


#now keep talking with the client

while 
:

    
#wait to accept a connection - blocking call
    conn, addr = s.accept()

    
print 
'Connected with ' + addr[
] + 
':' + 
str(addr[
])

     

    data = conn.recv(
)

    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 = 
 
# 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[
]) + 
' Message ' + msg[
]

    sys.exit()

     


print 
'Socket bind complete'

 


#Start listening on socket
s.listen(
)


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(
)

        reply = 
'OK...' + data

        
if 
not data: 

            
break

     

        conn.sendall(reply)

     

    
#came out of loop
    conn.
close()

 


#now keep talking with the client

while 
:

    
#wait to accept a connection - blocking call
    conn, addr = s.accept()

    
print 
'Connected with ' + addr[
] + 
':' + 
str(addr[
])

     

    
#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 = 
 
#Advisable to keep it as an exponent of 2
    PORT =

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

    
#this has no effect, why?
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 
)

    server_socket.bind((
"0.0.0.0", PORT))

    server_socket.listen(
)

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

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

while 
:

        
#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 =

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(
)

        
if 
not data:

            
raise 
EOFError(
'socket closed before we saw %r' % suffix)

        message += data

    
return message


def setup():

    
if 
len(sys.argv) != 
:

        
print >>sys.stderr, 
'usage: %s interface' % sys.argv[
]

        exit(
)

    interface = sys.argv[
]

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

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 
)

    sock.bind((interface, PORT))

    sock.listen(
)

    
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(
)

            
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. Python Network Programming

    @1: 同步网络编程(也就是阻塞方式) 同步网络编程一次只能连接一个客户端. Server端: import socket def debugPrint(name, value): print(&qu ...

  3. Neural Network Programming - Deep Learning with PyTorch with deeplizard.

    PyTorch Prerequisites - Syllabus for Neural Network Programming Series PyTorch先决条件 - 神经网络编程系列教学大纲 每个 ...

  4. [C1W2] Neural Networks and Deep Learning - Basics of Neural Network programming

    第二周:神经网络的编程基础(Basics of Neural Network programming) 二分类(Binary Classification) 这周我们将学习神经网络的基础知识,其中需要 ...

  5. 吴恩达《深度学习》-第一门课 (Neural Networks and Deep Learning)-第二周:(Basics of Neural Network programming)-课程笔记

    第二周:神经网络的编程基础 (Basics of Neural Network programming) 2.1.二分类(Binary Classification) 二分类问题的目标就是习得一个分类 ...

  6. Professional iOS Network Programming Connecting the Enterprise to the iPhone and iPad

    Book Description Learn to develop iPhone and iPad applications for networked enterprise environments ...

  7. SSL Programming Tutorial

    SSL Programming Tutorial � Table of Contents [ � Index       This section demonstrates the implement ...

  8. Fast portable non-blocking network programming with Libevent

    Fast portable non-blocking network programming with Libevent Fast portable non-blocking network prog ...

  9. Andrew's Blog / 《Network Programming with Go》学习笔记

    第一章: Architecture(体系结构) Protocol Layers(协议层) ISO OSI Protocol 每层的功能: 网络层提供交换及路由技术 传输层提供了终端系统之间的数据透明传 ...

随机推荐

  1. JS加入收藏与设置主页

    收藏: <a href="javascript:void(0)" onclick="shoucang(document.title,window.location) ...

  2. POJ3320 Jessica's Reading Problem(尺取+map+set)

    POJ3320 Jessica's Reading Problem set用来统计所有不重复的知识点的数,map用来维护区间[s,t]上每个知识点出现的次数,此题很好的体现了map的灵活应用 #inc ...

  3. Pythonchallenge一起来闯关(二)

    前情提要:Pythonchallenge一起来闯关(一) 这一篇来闯关10-15.感觉这几关比先前的难了不少,有的题目完全没思路. 10. 页面源码中的链接点击后有a = [1, 11, 21, 12 ...

  4. 跟我学android-Notification

    Notification 可以理解为通知的意思,会出现在通知栏,比如来了一条短信 使用 Notification 有以下3个步骤: 1. 创建 NotificationManager的对象 2.为No ...

  5. 【Usaco2008 Mar】土地购买

    [题目描述] 农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; ...

  6. C#程序中将图片转换为二进制字符串,并将二进制字符串转换为图片

    /// <summary> /// 将图片以二进制流 /// </summary> /// <param name="path"></pa ...

  7. Unity脚本获取内存和FPS

    using System; using System.Collections.Generic; using UnityEngine; public class Debugger : MonoBehav ...

  8. strcmp() Anyone?

    uva11732:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_prob ...

  9. Android入门之时间日期控件

    效果图: MainActivity.java package com.jkxqj.helloandroid; import android.app.Activity; import android.o ...

  10. static用法一

    #include "stdafx.h" #include "string.h" struct student { int num; ]; char sex; } ...