일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 파이썬
- recyclerview
- 명언모음
- 명심보감
- androidx
- DART
- 장자명언
- kotlin
- Streaming
- 넷플릭스
- 이모지
- 공자명언
- Coroutine
- ASMR
- Linux
- Firebase
- 소울칼리버6
- Flutter
- Android
- FSM
- 오픈소스
- 벤자민플랭클린
- 좋은글필사하기
- 이모지메모
- Freesound
- 1인개발자
- 코틀린
- jetpack compose
- 공부집중
- bash
Archives
- Today
- Total
Vintage appMaker의 Tech Blog
python에서 간단한 RPC 구현 (Ubuntu <--> Windows) 본문
Source code or Tip/python
python에서 간단한 RPC 구현 (Ubuntu <--> Windows)
VintageappMaker 2020. 12. 9. 09:59
해더
#pragma pack(push, 1)
// Header 정보
typedef struct tagPacketHeader{
CHAR identify[3]; // 인식자 PSW
int length; // 데이터 크기
BYTE encode; // 클라이언트 문자열 인코딩 종류(아직 미정)
BYTE req; // 0:shell, 1:python
} PacketData;
#pragma pack(pop)
ubuntu server
# -*- coding: utf-8 -*-
# 작성자: 박 성완(adsloader@naver.com)
# 목적 : 리눅스용 편리한 서버 사용
# 작성일: 2012.03.17
import socket
import threading
import SocketServer
import os
import struct
import binascii
import array
import base64
# packet 처리용 클래스
class Packet:
# 생성자: 변수 초기화용
def __init__(self):
self.m_pData = [] # Data 값
self.m_HDRSize = 9 # packet Header Size
#packet 관련 정의
self.struct = ' 3B l B B'
self.identify = []
# data 읽기함수
def ReadData(self, pRead):
tmp = []
try:
s = struct.Struct("<" + self.struct)
tmp = s.unpack(pRead)
print "unpack hdr:" , tmp
# 필드 자르기
self.identify = tmp[0:3]
self.length = tmp[3]
self.encode = tmp[4]
self.req = tmp[5]
except:
print "Structure Format Error!!"
return
# data 쓰기함수
def WriteData(self, clientID, req, pWrite):
try:
rst =[]
tmp = []
tmp += [ord('P'), ord('S'), ord('W')]
tmp.append(clientID)
tmp.append(req)
tmp.append(0)
tmp += pWrite
sFormat = "<" + self.struct + " %dB" % len(pWrite)
print sFormat
s = struct.Struct(sFormat)
rst = s.pack(*tmp)
return rst
except:
print "Structure Format Error!!"
return
# 클라이언트에서 호출할 함수
def TestFunc(str):
return "Test Func called with (%s)" % str
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
# command를 실행하기
def doShellCommand(self, sCmd):
pingaling = os.popen(u"%s"% sCmd)
sline = ""
while 1:
line = pingaling.readline()
sline += line
if not line: break
return sline
# python command를 실행하기
def doPythonCommand(self, sCmd):
result = ""
exec(sCmd)
print result
return result
def MakeSendCommand(self,p , sMsg ):
return p.WriteData(len(sMsg) + 1, 3, self.MakeString(sMsg))
def MakeString(self, sMsg):
# data영역 만들기
Data = []
#sData = bytes(sMsg)
sData = sMsg
for a in sData:
Data.append ( ord(a) )
Data.append(0)
return Data
def handle(self):
data = []
rcvdata = []
# function table 설정
CMD = {0:self.doShellCommand,1: self.doPythonCommand}
p = Packet()
nReadSize = p.m_HDRSize
MaxSize = nReadSize
bHeader = 0
while True:
rcvdata = self.request.recv(nReadSize)
# 소켓종료
if rcvdata == "":
break
# 버퍼링
if len(data) == 0 :
data = rcvdata
else:
data += rcvdata
# 패킷크기만큼 대기 한다.
if len(data) < MaxSize:
continue
# Header분석
if bHeader == 0:
p.ReadData(data)
nReadSize = p.length
MaxSize = p.m_HDRSize + nReadSize
bHeader = 1
continue
sData = unicode(data[9:-1],"cp949")
print sData
# 펑션테이블을 dictionary로 제어하다.
sline = CMD.get(p.req, self.doShellCommand )(sData)
wData = self.MakeSendCommand(p, sline )
self.request.send(wData)
data = []
def finish(self):
try:
print "closed"
except:
print "unknown error"
class ThreadedTCPServer(SocketServer.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = "", 9080
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
# False일 경우는 프로그램 종료안하고 데몬이 실행됨.
server_thread.setDaemon(False)
server_thread.start()
Windows Client
#include "stdafx.h"
#include "Packet.h"
char* UTF8ToANSI(const char *pszCode)
{
BSTR bstrWide;
char* pszAnsi;
int nLength;
nLength = MultiByteToWideChar(CP_UTF8, 0, pszCode, lstrlen(pszCode) + 1, NULL, NULL);
bstrWide = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_UTF8, 0, pszCode, lstrlen(pszCode) + 1, bstrWide, nLength);
nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL);
pszAnsi = new char[nLength];
WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, pszAnsi, nLength, NULL, NULL);
SysFreeString(bstrWide);
return pszAnsi;
}
// 이벤트 전송 - 소켓접속 및 전송 일괄처리
int SendEvent(int nEvnet, int nSize, BYTE* pData)
{
// int nInt = sizeof(CPacket::PacketData);
SOCKET sock;
SOCKADDR_IN dest_sin;
WORD wPort = 9080;
int rc;
// Create socket
sock = socket( AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
return INVALID_SOCKET;
}
// Set up IP address to access
memset (&dest_sin, 0, sizeof (dest_sin));
dest_sin.sin_family = AF_INET;
//dest_sin.sin_addr.S_un.S_addr = inet_addr ("10.0.2.15");
dest_sin.sin_addr.S_un.S_addr = inet_addr ("192.168.0.17");
dest_sin.sin_port = htons(wPort);
// Connect to the device
rc = connect( sock, (PSOCKADDR) &dest_sin, sizeof( dest_sin));
if (rc == SOCKET_ERROR) {
closesocket( sock );
return INVALID_SOCKET;
}
// 값 저장, 패킷전송, 패킷수신
CPacket pkt(sock);
pkt.SetHeader(nEvnet, 0);
// 데이터가 있다면 복사한다.
if( nSize > 0){
pkt.SetData(pData, nSize);
}
pkt.SendPacket();
pkt.Analyze();
// 읽은 정보 출력하기
char* szMsg = (char *)pkt.pPackData;
printf ("recived(%d):%s\r\n", strlen(szMsg), UTF8ToANSI(szMsg));
CPacket::PacketData* pInfo = pkt.GetPacketInfo();
closesocket (sock);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
if ( ( WSAStartup(0x101,&wsaData) ) != 0) {
WSACleanup();
return -1;
}
char* szMsg = "result = TestFunc('메롱')";
SendEvent(CPacket::PKT_PYTHON, strlen(szMsg)+1, (BYTE*)szMsg);
char* szMsg2 = "ps | grep 'python' && ls -al";
SendEvent(CPacket::PKT_SHELL, strlen(szMsg2)+1, (BYTE*)szMsg2);
return 0;
}
packet.h
/***************************************************************************
제목: packet Class
작성자: 박성완(adsloader@naver.com)
작성일: 2009.3.3
목적 : 패킷 전송 및 분석 클래스
참고 : Fixed Size
***************************************************************************/
#ifndef __PSW_PACKET__
#define __PSW_PACKET__
#include "stdafx.h"
#include <winsock.h>
class CPacket
{
public:
// 커맨드 정의
// 커맨드 정의
enum reqCMD{
PKT_SHELL = 0,
PKT_PYTHON
};
public:
#pragma pack(push, 1)
// Header 정보
typedef struct tagPacketHeader{
CHAR identify[3]; // 인식자 PSW
int length; // 데이터 크기
BYTE encode; // 클라이언트 문자열 인코딩 종류(아직 미정)
BYTE req; // 0:shell, 1:python
} PacketData;
#pragma pack(pop)
public:
CPacket(SOCKET s);
virtual ~CPacket();
int Analyze();
int SetHeader( BYTE req, BYTE ack);
int SendPacket(int nSize, byte* pData);
int SetData(byte* pData, int nSize);
int SendPacket();
BYTE* GetPacketData();
PacketData* GetPacketInfo();
// Data영역
BYTE* pPackData;
private:
SOCKET m_socket;
PacketData m_pkt;
// nSize읽을때까지 계속 버퍼링 및 블럭한다.
int RecvBySize(char* pData, int nSize);
};
#endif
실행하기
- 우분투에서 ububtu_server.py를 실행한다.
- 윈도우에서 클라이언트 소스를 vs2008에서 컴파일하여 실행한다.
- 서버에서 클라이언트의 접속을 처리한다.
- 클라이언트에서 result = TestFunc('메롱') 을 파이썬 명령어로 요청한다.
- 클라이언트에서 ps | grep 'python' && ls -al 을 리눅스 쉘 명령어로 요청한다.
'Source code or Tip > python' 카테고리의 다른 글
python에서 case - 딕셔너리와 함수 (0) | 2020.12.30 |
---|---|
[github] 파이썬 확장모듈(C++) 만들기 (0) | 2020.12.03 |
스크래치 2.0 HTTP Extension 만들기 (0) | 2020.11.10 |
우분투 python에서 ncurses (0) | 2020.11.09 |
python selenium을 이용한 브라우저 제어 (0) | 2020.07.29 |
Comments