socket跨平台编程及其简单应用

1. 目的及意义
1) 网络通信
第二次机器革命潮起时期,物联网、云计算、大数据如火如荼,网络通信技术是基础;
网络通信应用很多,不仅局限于通信,与其他技术结合可以实现很多有趣、有用的应用;特别是WiFi,这个既有的不需要新建设的、逐渐普及的、有很大潜力的技术,仅举几例:


WiFi时代如何通信 网络电话应用深度思考
http://www.kejixun.com/article/201404/34525.html
WiFi电话一定程度上替代普通电话;


卫星定位技术获取位置,通过通信技术将位置信息传可以实现目标位置监控,目前已有老人、小孩、物品防丢失的商用产品;


麻省理工新技术:借WiFi信号“透视”墙体
http://tech.sina.com.cn/t/2013-06-28/11418489359.shtml
通过特殊编码监测发射和接收信号特征实现目标特性识别;


麻省理工学院 上网的WiFi也能知道你健不健康
http://www.39yst.com/xinwen/20150427/261462.shtml
通过特殊编码监测发射和接收信号特征实现人体状态监测;


2) socket
在众多网络编程方法中,选择底层socket灵活、高效,同时适用于PC/laptop/手机,有线/无线,Windows/linux等各种平台;


3) 编程工具/平台
计算机端使用Python,手机端使用Android/Python。

编程工具配置和使用占了初学者很多精力,另文详述?


4) 定位
从底层开始开发一个完整的应用需要大量的知识、精力,本文实现socket了解、底层基础编程及其模块化以便后续开发,简单地聊天应用以验证和拓展底层基础编程,作为网络通信技术一个基础尝试和后续开发的基础。


2. Android/Python Socket编程基础
另文细述


3. 设计及实现

usr_info_stat数据结构:
name – passwd – stat(login/logout)

命令结构:
#[ type]#[param1]#[param2]
login     [name]  [passwd]
logout    [name]  [passwd]
msg [from] [to ]

细节信息在代码注释中已经清楚标明。

 

Python程序chip_udp_server.py/chip_udp_client.py可以运行在PC/laptop的activePython和Android的Qpython;
Java程序可以在Android以App形式运行;

Python Server端程序:

#!/usr/bin/env python

# =============================================================================
#                  Copy Rights @Chip, All Rights Reserved
#
# File: chip_udp_server.py
# Description:
#     udp server program
# HOWTORUN:
#     just start it
# V0.1: Initial Version
#       Chip,2015/6/10
# V0.2: Add server account.
#       Chip, 2015/6/13
# V1.0: add ip/port setting
#       Chip,2015/6/21
# ToDo: 1. printv for all kinds of string.
#       2. msg_proc, reply/resend. - done
#       3. multi user
#       4. bind ip to usr
#       5. free receive/send
#       6. Any IP address
#       7. Android
#
# =============================================================================

# -----------------------------------------------------------------------------
# 1. start/import
# -----------------------------------------------------------------------------

print('1. chip_udp_server.py start/import','\n');

import sys,socket,time

# -----------------------------------------------------------------------------
# 2. data structure
# -----------------------------------------------------------------------------

print('2. data structure','\n');

# FIXME: better data structure?
usr_name = ['John','Tom','Ben','Server']
usr_passwd = ['J123','T123','B123','S123']
usr_stat = ['logout','logout','logout','logout']
usr_addr = ['192.168.0.1','192.168.0.1','192.168.0.1','192.168.0.1']
usr_num = 4

# -----------------------------------------------------------------------------
# 3. input processing
# -----------------------------------------------------------------------------

print('3. input processing','\n\n');

ostr = "Server listen to IP=localhost, port=12345 as default. \n \
type y to use default settings, type n to specify \n"
print(ostr);

istr = sys.stdin.readline().strip()
if ( istr == 'y' ):
        host = 'localhost' #sys.argv[1]
        port = 12345       #sys.argv[2]
elif ( istr == 'n' ):
        ostr = "Pls specify the IP to listen to"
        print(ostr);
        host = sys.stdin.readline().strip()
        ostr = "Pls specify the port to listen to"
        print(ostr);
        port = sys.stdin.readline().strip()
else:
        ostr = "setting error!"
        print(ostr);
        sys.exit()

print('--------------------------\n')        
ostr = "setting is:"
print(ostr)
print(host,port,'\n')
print('--------------------------\n')

verbose   = 1
test_mode = 0

# -----------------------------------------------------------------------------
# 4. function
# -----------------------------------------------------------------------------

print('4. function','\n');

# -----------------------------------------------
# 4.1 utility
# -----------------------------------------------

def printv(msg):
        if (verbose ==1):
                print(msg);

def print_usr_info_stat():
        print('\nprint_usr_info_stat:');
        for i in range(0,usr_num):
                print(i,usr_name[i],usr_passwd[i],usr_stat[i],usr_addr[i]);
        print('\n');
	
# -----------------------------------------------
# 4.2 usr info stat proc
# -----------------------------------------------

# login
def login(name,passwd,addr):
        valid = 0;
        for i in range(0,usr_num):
                if (usr_name[i] == name and usr_passwd[i] == passwd):
                        usr_stat[i] = 'login';
                        usr_addr[i] = addr;                         
                        if (1 == test_mode):
                                print(name,passwd,addr,': login\n');
                        else:
                                s.sendto(b'login succeed', addr)
                                print('reply: ',name,'login succeed');
                        valid = 1;
        if (0 == valid):
                if (1 == test_mode):
                        print('usr name not found/wrong passwd\n');
                else:
                        s.sendto(b'login fail', addr)
                        print('reply: ',name,'usr name not found/wrong passwd\n');

# logout  
def logout(name,passwd,addr):
        valid = 0;
        for i in range(0,usr_num):
                if (usr_name[i] == name):
                        usr_stat[i] = 'logout';
                        usr_addr[i] = 'xxx';
                        if (1 == test_mode):
                                print(name,': logout\n');
                        else:
                                s.sendto(b'logout succeed', addr);
                                print('reply: ',name,'logout succeed');
                        valid = 1;
        if (0 == valid):
                if (1 == test_mode):
                        print('usr name not found/wrong passwd\n');
                else:
                        s.sendto(b'logout fail', addr)
                        print('reply: ',name,'logout fail');
						
def chk_login(from_name,to_name,addr):
        valid = 0;
        for i in range(0,usr_num):
                if (usr_name[i] == from_name):
                        for j in range(0,usr_num):
                                if (usr_name[j] == to_name):
                                        if ( usr_stat[i]=='login' and usr_stat[j] == 'login'):
                                                valid = 1;
                                                if (1 == test_mode):
                                                        print('chk_login pass');
                                                return(1);
        if(valid == 0):
                if (1 == test_mode):
                        print('check login fail\n');
                else:
                        s.sendto(b'check login fail', addr)
                        print('reply: ',from_name,to_name,'check login fail\n');
                return(0);

# -----------------------------------------------
# 4.3 main proc
# -----------------------------------------------

# msg_dispatch
def msg_proc(from_name,to_name,to_msg,addr):
        if (1 == chk_login(from_name,to_name,addr)):
                if (1 == test_mode):
                        print('server got it\n');
                else:
                        #s.sendto(b'server got it\n',addr)
                        #print('reply: ','server got it\n');
                        print ("Enter: ")
                        data = sys.stdin.readline().strip()
                        #s.sendall(data.encode())
                        s.sendto(data.encode(),addr)
                        print('reply: \n',data);
                        
# decode and dispatch
def decode_dispatch(message,addr):
        # print user information
        #if (1 == test_mode):
        #        print_usr_info_stat();
        
        # input        
        if (1 == test_mode):
                msg = message.split('#');
                print('splited msg:',msg,addr);
        else:
                a = message.decode();
                msg = a.split('#');
                print('received from:',addr,'\n messgae:',message);
                
        # message processing
        if(msg[1] == 'login'):
                login(msg[2],msg[3],addr);
        elif(msg[1] == 'logout'):
                logout(msg[2],msg[3],addr);
        elif(msg[1] == 'msg'):
                msg_proc(msg[2],msg[3],msg[4],addr); 
        print('\n');

# -----------------------------------------------------------------------------
# 5. main
# -----------------------------------------------------------------------------

'''   '''
# ----------------------------------------------------
# 5.1 connect
# ----------------------------------------------------

print('5.1 connect','\n');

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))

# ----------------------------------------------------
# 5.2 main loop
# ----------------------------------------------------	

print('5.2 main loop','\n');

while 1:
    try:
        message,address = s.recvfrom(8192)
        decode_dispatch(message,address)
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        traceback.print_exc()


# -----------------------------------------------------------------------------
# 6. incermental/regression test (FIXME: auto) 
#    Usage: comment out main then you can make test
# -----------------------------------------------------------------------------

'''
print('6. incermental/regression test\n');

# ------------------------------------------------
# 6.1 verbose test
# ------------------------------------------------

print('verbose test start');
print('------------------------------------------\n');

verbose = 1
printv('verbose test,if you see this msg,test pass');
# printv('verbose test,if you see this msg,test pass',verbose);

verbose = 0;
printv('verbose test,if you see this msg,test fail');

print('verbose test end');
print('------------------------------------------\n');
'''   

# ------------------------------------------------
# 6.2 usr info test
# ------------------------------------------------

'''
print('usr info test start\n');
print('------------------------------------------\n');

# login case
login('Ben','B123' ,'192.168.0.6');
login('Tom','T123' ,'192.168.0.7');
login('John','J123','192.168.0.8');
print_usr_info_stat()

# logout case
logout('Ben', 'B123','192.168.0.6');
logout('Tom', 'T123','192.168.0.7');
logout('John','J123','192.168.0.8');
print_usr_info_stat();

chk_login('Ben','John','192.168.0.8');

login('Ben','B123' ,'192.168.0.6');
login('Tom','T123' ,'192.168.0.7');
login('John','J123','192.168.0.8');

chk_login('Ben','John','192.168.0.8');

print('\nusr info test end');
print('------------------------------------------\n');
'''   

# ------------------------------------------------
# 6.3 test decode_dispatch
#     NOTEME: decode needed to be comment out
# ------------------------------------------------

'''   
print('test decode_dispatch start\n');
print('------------------------------------------\n');

#
print('Round1:\n');
message1 = '#login#John#J123#'
message2 = '#logout#John#J123#'
message3 = '#msg#John#Tom#Hi,how are doing?'
message4 = '#msg#Tom#John#Very good!'

decode_dispatch(message1,'192.168.0.6');
decode_dispatch(message2,'192.168.0.7');
decode_dispatch(message3,'192.168.0.8');
decode_dispatch(message4,'192.168.0.9');

#
print('Round2:\n');
message2 = '#login#Tom#T123#'

decode_dispatch(message1,'192.168.0.6');
decode_dispatch(message2,'192.168.0.7');
decode_dispatch(message3,'192.168.0.8');
decode_dispatch(message4,'192.168.0.9');

print('test decode_dispatch end\n');
print('------------------------------------------\n');
'''

# ------------------------------------------------
# 6.4 function test
#     Usage: turn main loop,set test_mode = 0
#            use cmd from decode_dispatch at client end
# ------------------------------------------------

# -----------------------------------------------------------------------------
# 7. end
# -----------------------------------------------------------------------------

print('\nchip_udp_server.py end','\n');


 
 Pyhont Client端程序:

 

#!/usr/bin/env python

# =============================================================================
#                  Copy Rights @Chip, All Rights Reserved
#
# File: chip_udp_client.py
# Description:
#     udp client program
#     #[cmd type]#[param1]#[param2]#
#       login - user name - passwd
#      logout - user name - passwd
#        msg -   from     - to
#     Please refer to chip_udp_server.py Line 36-41 for detailed infomation
# HOWTORUN:
#
# V0.1: Initial Version
#       Chip,2016/6/10
# V1.0: add ip/port setting
#       Chip,2015/6/21
#
# =============================================================================

# -----------------------------------------------------------------------------
# 1. start/import
# -----------------------------------------------------------------------------

print('1. start/import','\n');

import sys,socket,time

# -----------------------------------------------------------------------------
# 2. data structure
# -----------------------------------------------------------------------------

print('2. data structure','\n');

# -----------------------------------------------------------------------------
# 3. input processing
# -----------------------------------------------------------------------------

print('3. input processing','\n');

ostr = "Clent listen to IP=localhost, port=12345 as default. \n \
type y to use default settings, type n to specify \n"
print(ostr);

istr = sys.stdin.readline().strip()
if ( istr == 'y' ):
        host = 'localhost'       #sys.argv[1]
        textport = '12345'       #sys.argv[2]
elif ( istr == 'n' ):
        ostr = "Pls specify the IP to connect to"
        print(ostr);
        host = sys.stdin.readline().strip()
        ostr = "Pls specify the port to connect to"
        print(ostr);
        textport = sys.stdin.readline().strip()
else:
        ostr = "setting error!"
        print(ostr);
        sys.exit()

print('--------------------------\n')        
ostr = "setting is:"
print(ostr)
print(host,textport,'\n')
print('--------------------------\n')

# host = 'localhost' #sys.argv[1]
# textport = '51423' #sys.argv[2]

# -----------------------------------------------------------------------------
# 4. function
# -----------------------------------------------------------------------------

print('4. function','\n');

# -----------------------------------------------------------------------------
# 5. main
# -----------------------------------------------------------------------------

'''   '''
print('5. main','\n');

# ----------------------------------------------------
# 5.1 connect
# ----------------------------------------------------

print('5.1 connect','\n');

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# ----------------------------------------------------
# 5.2 main loop
# ----------------------------------------------------	

print('5.2 main loop','\n');

ref = "\n \
Reference msg example: \n \
    #login#John#J123# \n \
    #login#Tom#T123# \n \
\n \
    #msg#John#Tom#Hi,how are doing? \n \
    just put msg behind \"#msg#[]#[]#[]\" \n \
\n \
    if you want to quit, example as #logout#John#J123# \n \
"
print(ref);

try:
    port = int(textport)
except ValueError:
    # That didn't work. Look it up instread.
    port = socket.getservbyname(textport, 'udp')
    
while 1:
    # connect
    s.connect((host, port))

    # input
    print ("Enter: ")
    data = sys.stdin.readline().strip()

    # send
    s.sendall(data.encode())
    s.shutdown(1)
    print ("Looking for replies; press Ctrl-C or Ctrl-Break to stop.")

    # receive
    buf = s.recv(2048)
    if not len(buf):
        break
    print ("Received:\n %s\n" % buf)

# -----------------------------------------------------------------------------
# 6. incermental/regression test (FIXME: auto) 
#    Usage: comment out main then you can make test
# -----------------------------------------------------------------------------

print('6. incermental/regression test\n');

# -----------------------------------------------------------------------------
# 7. end
# -----------------------------------------------------------------------------

print('\nchip_udp_server.py end','\n');


 

Android/Java程序:

 

package org.crazyit.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SimpleClient extends Activity
{
 EditText show;
 @Override
 public void onCreate(Bundle savedInstanceState)
 {
 try{
  // 创建一个DatagramSocket对象
  DatagramSocket socket = new DatagramSocket(51423);

  //创建一个InetAddree
  InetAddress serverAddress = InetAddress.getByName("192.168.1.105");
  String str = "#login#John#J123#";  // 要传输的数据
  byte data [] = str.getBytes();     
  
  //创建一个DatagramPacket对象,并指定要地址以及端口号
  DatagramPacket packet = new DatagramPacket(data,data.length,serverAddress,51423);
  
  //调用socket对象的send方法,发送数据
  socket.send(packet);
 } 
 
 catch (Exception e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 }
}

 

AndroidManifest.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="org.crazyit.net"
   android:versionCode="1"
   android:versionName="1.0">
 <application android:icon="@drawable/icon" android:label="@string/app_name">
  <activity android:name=".SimpleClient"
      android:label="@string/app_name">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>

 </application>
 <!--  授权访问互联网-->
 <uses-permission android:name="android.permission.INTERNET"/> 
</manifest> 

 

4. 运行及测试
本程序使用ActivePython 3.3平台。
运行程序,交互过程如下图所示:

Server Log

 

Client Log 

 第二张图片不能上传??? 

Android平台使用QPython

 第三张图片不能上传??? 

Android使用Java


5. 后记
已经实现的详情参见运行及测试;
后续提升项参见chip_udp_server.py文件头
经验之谈,但一家之言;持续更新,欢迎探讨。

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值