Python Socket,How to Create Socket Server? - 网络编程实例

文章出自:Python socket – network programming tutorial by Silver Moon

原创译文,如有版权问题请联系删除。

Network programing in Python:

Part2: Programing sockets servers.

在所有的通信实例中,都分为Client 和Server. 其中:Client是请求的发起点,Server是使用Socket接收传入的值并且提供返回数据。

  Server的职能如下:

  1>.创建/打开一个socket

  2>.绑定IP地址(端口) (Bind IP with port)

  3>.监听请求的连接(Listen for incoming conecting)

  4>.同意连接(Accpect connecting)

  5>.读取/发送

  OK,到此,我们明白了server要做什么和怎么做(上面所描述的代码执行的顺序也是不能随意修改的)。在上一节点Part1中,我们已经掌握如何创建和打开一个socket,

接下来我们就要学习如何绑定和监听。

  Bind a socket:  

#!/usr/bin/python
import socket   #for sockets
import sys  #for exit

HOST = ''   #HOST name or IP address
PORT = 7001             #remote port

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Socket created')

try:
    s.bind((HOST,PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()     
print ('Socket bind complete')

  现在,利用IP地址和端口的绑定已经完成了,在绑定之前,你必须确保所有的请求方的数据能够通过这个端口被访问,接下来开始监听连接,当然不排除多个不同的程序监听同一个端口的情况。(如何处理这样的情况??!)

  Listen for incoming connections:

  成功绑定之后,要监听这个连接,方法:socket_listen用来监听,只需要在bind()成功后加上如下代码即可:  

#listen connecting
s.listen(10) #why we input 10, you can read manual about listen function
print('Socket now listening')

  Accept connection:

  方法: socket_accpect用来接收请求。  

#!/usr/bin/python
import socket   #for sockets
import sys  #for exit

HOST = ''   #HOST name or IP address
PORT = 7001             #remote port

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Socket created')

#bind ip/port
try:
    s.bind((HOST,PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')

#listen connecting
s.listen(10)
print('Socket now listening')

#wait to accept a connection - blocking call
conn, addr = s.accept()
 
#display client information
print ('Connected with ' + addr[0] + ':' + str(addr[1]))

  结果输出:

  

  现在程序已经开始等待请求数据从port 7001, 不要关闭程序,让它保持运行,我们看看会得到什么...

  Receving/send Data:  

#!/usr/bin/python
import socket   #for sockets
import sys  #for exit

HOST = ''   #HOST name or IP address
PORT = 7001             #remote port

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Socket created')

#bind ip/port
try:
    s.bind((HOST,PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')

#listen connecting
s.listen(10)
print('Socket now listening')

#wait to accept a connection - blocking call
conn, addr = s.accept()
 
#display client information
print ('Connected with ' + addr[0] + ':' + str(addr[1]))

#now keep talking with the client
data = conn.recv(1024)
print(data)
conn.sendall(data)
 
#close and dispoiled socket
conn.close()
s.close()

  然后连接到这台server,需要注意的是如果防火墙开启,要注意设置的端口是否可以安全访问。如果答案是肯定的,你将看到:

  

  现在我们已经完成了一个绑定/监听/同意请求的一个完整连接,但是你会发现,在代码执行完成并返回'Hello'后会退出,这样的设计是效率非常低下的,实际上我们的很多逻辑是在接收完成数据后才执行的。

  在现实使用的应用场景中,我们的server需要的是 Keep running non-stop, 有一种方法就是将Accpect()方法放在循环中,这样的话它将会一直接收客户端发来的请求。  

  Live Server:

  顾名思义,一直运行(监听客户端请求并同意处理请求)。  

#!/usr/bin/python
import socket   #for sockets
import sys  #for exit

HOST = ''   #HOST name or IP address
PORT = 7001             #remote port

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Socket created')

#bind ip/port
try:
    s.bind((HOST,PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')

#listen connecting
s.listen(10)
print('Socket now listening')

#simple way as server
#-------------------------------------------------------
#wait to accept a connection - blocking call
#conn, addr = s.accept()
 
##display client information
#print ('Connected with ' + addr[0] + ':' + str(addr[1]))

##now keep talking with the client
#data = conn.recv(1024)
#-------------------------------------------------------

#liver server, always running
#-------------------------------------------------------
#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(data)
    print(data)
#------------------------------------------------------- 
#close and dispoiled socket
conn.close()
s.close()

  输出结果:

  server:

  

  client:

  

  到目前为止,我们做的不错,但是这个不是一个有效的网络通信实例,server端的代码在一个循环中同意client的请求并回应给他们,然后并没有针对接收到的请求的数据做任何的处理,同时它也没有能力处理同一时间的多个请求,现在我们就来处理这个问题。

  Handling Connections:

  想要处理每个请求连接,我们需要一个独立的代码处理逻辑和一台独立的服务器,有一种办法就是使用多线程,主服务器同意请求然后创建一个线程去管理这个请求,然后服务器返回在继续处理其他请求。  

#!/usr/bin/python
import socket   #for sockets
import sys  #for exit
import threading
# from thread  import *

HOST = ''   #HOST name or IP address
PORT = 7001             #remote port

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print ('Socket created')

#bind ip/port
try:
    s.bind((HOST,PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')

#listen connecting
s.listen(10)
print('Socket now listening')

#simple way as server
#-------------------------------------------------------
#wait to accept a connection - blocking call
#conn, addr = s.accept()
 
##display client information
#print ('Connected with ' + addr[0] + ':' + str(addr[1]))

##now keep talking with the client
#data = conn.recv(1024)
#-------------------------------------------------------

#liver server, always running
#-------------------------------------------------------
#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(data)
#    print(data)
##------------------------------------------------------- 

#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,))
  threading._start_new_thread(clientthread ,(conn,))
#close and dispoiled socket conn.close() s.close()

  输出结果:

  server:

  

  Client:

  

  So,现在我们拥有了一个server,它是一个很棒的学你说话的机器人,HAHA

  Conclusion:

  截至目前,我相信你已经掌握了在Python中基础的socket网络编程,你可以尝试创建其他的社交客户端或与其相近的实例。至此,放学。不会再讲5分钟。

  Bug fix:

  开发环境: Python3.4 + ptvs

  以上代码均已通过测试,当然不排除Python版本不一样的情况,实际上我也在原作者的基础上修改了很多,如果有bug的话,欢迎指正。  

 

posted on 2015-09-25 21:00  星小野  阅读(876)  评论(0编辑  收藏  举报