关于网络编程以及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. C#错误异常列表

    Exception: 所有异常对象的基类. SystemException:运行时产生的所有错误的基类. IndexOutOfRangeException:当一个数组的下标超出范围时运行时引发. Nu ...

  2. (转)教你如何使用php session

    学会php session可以在很多地方使用,比如做一个后台登录的功能,要让程序记住用户的session,其实很简单,看了下面的文章你就明白了.     PHP session用法其实很简单它可以把用 ...

  3. 黑马程序员-hashtable

    散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列 ...

  4. 创建 序列 存储过程 job

    掌握了 oracle中的 dbms_lock 函数,该函数 主要用于暂停执行的程序 1.用意 写job 以10分钟 为单元,前10分钟 从 1到10 插入测试表, 中间10分钟从 11到20插入测试表 ...

  5. C#使用Expand、Shell32解压Cab、XSN文件

    前言: 需要解压InfoPath表单的xsn文件,在项目中以前使用的是Expand命令行解压,都没有出过问题,近段时间项目中突然报错解压失败,通过分析解压操作得出结论: 1.正常正常情况下,expan ...

  6. javascript 操作符类型隐性转换

    javascript 操作符类型隐性转换 (一).一元操作符只能操作一个值的操作符叫做一元操作符1.递增和递减操作符a. 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作 ...

  7. 【USACO 2.1.3】三值的排序

    [题目描述] 排序是一种很频繁的计算任务.现在考虑最多只有三值的排序问题.一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候.在这个任务中可能的值只有三种1,2和3.我们用交换的方法把他排 ...

  8. Python正则表达式+自创口诀

    重新学习了Python正则表达式,看了一些很好的学习博客,向大家推荐这个. 感谢作者@AstralWind 博客地址:http://www.cnblogs.com/huxi/archive/2010/ ...

  9. linux处理闰秒

    闰秒的介绍可以参考维基百科 https://zh.wikipedia.org/wiki/闰秒 linux处理闰秒 Linux使用UTC时钟,并通过NTP (Network time protocol) ...

  10. Linux_hadoop_install

    1. Build Linux env my env is VM RedHat Linux 6.5 64bit    set fixed IP                  vim /etc/sys ...