关于网络编程以及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. ASP.NET 日志

    ASP.NET5已经内建集成了日志系统,你也可以用第三方的日志框架. 1. 在你的应用程序中实现日志 在Startup.cs文件中,在Configure里可以把ILoggerFactory注入进去,然 ...

  2. 巧妙的Jq仿QQ游戏导航界面学习

    先贴上源代码 <!doctype html> <html> <head> <meta charset="utf-8"> <ti ...

  3. UIScrollView 之图片缩放

    UIScrollView 之图片缩放 有些时候,我们可能要对某些内容进行手势缩放,如下图所示 UIScrollView不仅能滚动显示大量内容,还能对其内容进行缩放处理 也就是说,要完成缩放功能的话,只 ...

  4. SqlDependency 的使用

    1.SqlDependency是什么: SqlDependency 对象表示应用程序和 SQL Server 实例间的查询通知依赖关系.应用程序可以创建一个 SqlDependency 对象并进行注册 ...

  5. apache-maven-3.3.9集成apache-tomcat-7.0.72实现热部署配置细节

    1.开发环境.Maven.Tomcat安装不作描述,搜索引擎很多文章可供参考. 2.Tomcat配置文件修改 1)Tomcat管理权限配置 1.1)在tomcat安装目录下找到tomcat-users ...

  6. Action class [userAction] not found

    今天在做SSI框架整合的时候报了一个这样的错误:Action class [userAction] not found - action - file:F:\workspace\.metadata\. ...

  7. Bootstrap_排版_标题

    Bootstrap和普通的HTML页面一样,定义标题都是使用标签<h1>到<h6>,只不过Bootstrap覆盖了其默认的样式,使用其在所有浏览器下显示的效果一样,具体定义的规 ...

  8. 使用微妙计算PHP脚本执行时间

    在PHP中,大多数的时间格式都是以UNIX时间戳表示的,而UNIX时间戳是以s(秒)为最小的计量时间的单位.这对某些应用程序来说不够精确,所以可以调用microtime()返回当前UNIX时间戳和微妙 ...

  9. 死亡的协议--- Pieter Hintjens (ZeroMQ作者)

    过去几年中用zeromq写过几个系统系统.对ZeroMQ强大和灵活印象非常深刻.在阅读zeromq guide文档时候.发现作者整理各种通信模式非常经典和实用,可以作为分布式通信的教科书来看.第一次见 ...

  10. UVA 1600 Patrol Robot(机器人穿越障碍最短路线BFS)

    UVA 1600 Patrol Robot   Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu   ...