2016年2月2日 星期二

python socket programming

本文是依據Ref 1來的...

client site


lesson 1 : create a socket and add error handling

#handling errors in python socket programs
import socket   #for sockets
import sys  #for exit
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
print 'Socket Created'

lesson 2 :   connect to an server, get the ip address

import socket   #for sockets
import sys  #for exit
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
print 'Socket Created'
host = 'www.google.com'
try:
    remote_ip = socket.gethostbyname( host )
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip


指定了 host name...呼叫 gethostbyname() 來得到 ip address..

lesson 3 :  add connect

import socket   #for sockets
import sys  #for exit
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
print 'Socket Created'
host = 'www.google.com'
port = 80
try:
    remote_ip = socket.gethostbyname( host )
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip
#Connect to remote server
s.connect((remote_ip , port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip

   呼叫 socket.connect() 來連線到server



lesson 4 :  sending data

import socket   #for sockets
import sys  #for exit
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
print 'Socket Created'
host = 'www.google.com'
port = 80
try:
    remote_ip = socket.gethostbyname( host )
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip
#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'

呼叫  socket.sendall() 來傳送資料....  "GET / HTTP/1.1\r\n\r\n"
執行內容如下:

因為傳送沒有發生error  (socket.error 沒有被觸發)
所以沒有印出 "Send failed"

lesson 5 :  receiving data

#Socket client example in python
import socket   #for sockets
import sys  #for exit
#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 = 80;
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'
#Now receive data
reply = s.recv(4096)
print reply

呼叫 socket.recv() 並且把接收到的資料放在 reply 變數

執行結果如下:



lesson 6 :  close socket

s.close()

在最後加入這行就可以

==================================================

server site


lesson 1 : Bind a socket

import socket
import sys
HOST = ''   # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
    s.bind((HOST, PORT)) # it must has two ()..
except socket.error , msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()
     
print 'Socket bind complete'

一樣是先建立一個socket 物件的變數s..... 初始化的方式是呼叫  socket.socket()

然後呼叫 socket.bind(HOST,PORT)  函式來建立server.....

這邊PORT 設定為8888
HOST        設定為''

執行結果如下:



lesson 2 : Listen for incoming content

其實就是在後面多加兩行
s.listen(10)
print 'Socket now listening'


lesson 3 : accept connection

import socket
import sys
HOST = ''   # Symbolic name meaning all available interfaces
PORT = 8888 # 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[0]) + ' Message ' + msg[1]
    sys.exit()
     
print 'Socket bind complete'
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])

呼叫  socket.accept()  ... 傳回值為 conn, addr......

  用 putty 登入那台電腦....記得port 要填8888

 就會看到下面的結果.... 我用ip : 192.168.1.4 的NB 來登入



lesson 4:  send and receive data

import socket
import sys
HOST = ''   # Symbolic name meaning all available interfaces
PORT = 8888 # 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[0]) + ' Message ' + msg[1]
    sys.exit()
     
print 'Socket bind complete'
s.listen(10)
print 'Socket now listening'
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#now keep talking with the client
data = conn.recv(1024)
conn.sendall(data)
conn.close()
s.close()


為了測試這個server code....我用另外一台RPI ....然後把剛剛client 端的程式改寫

vi   client.py


import socket   #for sockets
import sys  #for exit

#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 = '192.168.1.2'
port = 8888

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 = "Hello world"

try :
    #Set the whole string
    s.sendall(message)
except socket.error:
    #Send failed
    print 'Send failed'
    sys.exit()

print 'Message send successfully'


#Now receive data
reply = s.recv(4096)

print reply

s.close()

======================================================

從 client 端的程式來看....我預先知道server的ip address...(去server 那邊打ifconfig)

然後把 host = '192.168.1.2' .... port 改成 8888

把送出去的資料改成  Hello world

執行結果如下:

server 端的結果如下:




client 端的結果如下:



可以看到client 接收到剛剛傳給server的訊息

===============================================================

Live server


lesson 1 : add while loop
import socket
import sys
HOST = ''   # Symbolic name meaning all available interfaces
PORT = 5000 # 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[0]) + ' Message ' + msg[1]
    sys.exit()
     
print 'Socket bind complete'
s.listen(10)
print 'Socket now listening'
#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(reply)
conn.close()
s.close()


其實就是差在多了一個 while 迴圈......一直去執行 accept()

終止迴圈的條件是判斷有人送的空資料過來.....


lesson 2: handle connection

import socket
import sys
from thread import *
HOST = ''   # Symbolic name meaning all available interfaces
PORT = 8888 # 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[0]) + ' Message ' + msg[1]
    sys.exit()
     
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
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(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,))
s.close()

當一個server 不能只執行單一個thread... 為了要能夠多工.....我們必須使用 multi-thread

執行結果如下:





reference 1 : http://www.binarytides.com/python-socket-programming-tutorial/

沒有留言:

張貼留言