您的位置:首页 > 编程语言

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

2015-06-12 16:08 369 查看

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文件头
经验之谈,但一家之言;持续更新,欢迎探讨。

 

 


 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: