关于网络编程以及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. iOS和hybird移动端性能

         作为一名写了⑦年代码的程序员,目前我最擅长的领域是IOS的客户端开发,在移动领域的开发时间2年. ⑦年前,我刚入行的时候,曾经认为自己将会永远做一个LINUX 服务端C++程序员,于是花了大 ...

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

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

  3. C++ 异常处理执行过程

    看<clean code>时,又遇到异常处理的例程. 看不明白是因为我一直都将异常处理束之高阁. 今天晚上下决心去找资料看看,看完之后觉得以前是把它想得太难,其实非常简单. 希望以后遇到问 ...

  4. 用 javascript 判断 IE 版本号

    原文地址: http://julying.com/blog/determine-the-version-number-of-ie-with-javascript/ var _IE = (functio ...

  5. Oracle 体系结构及安全管理

    1 oracle数据库服务器构成:数据库和实例2 oracle内部结构: 物理存储结构: 数据文件(xxx.dbf):存放数据 控制文件(xxx.ctl):控制数据库的完整性恢复数据或使用的日志文件 ...

  6. Thinkphp 表单验证

    在服务器端通过tp框架实现表单验证 用户名.密码.重复密码.邮箱.qq.手机号码.爱好.学历 具体步骤: 制作表单 表单form数据通过create()方法收集(验证功能要求我们必须通过create( ...

  7. jQuery操作cookie

    验证jquery的cookie插件时才知道原先文件一直在桌面上放着执行发现没有效果,文件必须放在web服务器下面执行才会生效,晕菜! $.cookie(name,value,{expires: 7,p ...

  8. [转载]在 Windows 10 中, 如何卸载和重新安装 OneNote App

    在 Windows 10 中, 如何卸载和重新安装 OneNote App 15/8/2015 使用 PowerShell 命令卸载 OneNote App 开始菜单 -> 输入 "P ...

  9. Autoit 获取运行目录

    #include <File.au3> #include <MsgBoxConstants.au3> MsgBox($MB_SYSTEMMODAL, "", ...

  10. JS和正则表达式验证手机号码、邮箱等

    <-------------------------------------验证手机号码---------------------------------------------> fun ...