python) TCP_Socket 을 이용한 회원관리 프로그램

 

 

 

 

Server

In [1]:
class MsgObj:
    def __init__(self,num,msg):
        self.num=num
        self.msg=msg
    
    def __str__(self):
        return f'{self.num}\t{self.msg}'
In [2]:
class User:
    def __init__(self,num,name=None,phone=None,email=None):
        self.num=num
        self.name=name
        self.phone=phone
        self.email=email
    def __str__(self):
        return f'{self.num}\t{self.name}\t{self.phone}\t{self.email}'
    def __eq__(self,other):
        return True if self.num==other.num else False
    def getStr(self):
        return f'{self.num}\t{self.name}\t{self.phone}\t{self.email}'
In [3]:
# 통신 준비
from socket import * #socket.xxx
import time
import pickle
import threading

serverSock=socket(AF_INET,SOCK_STREAM)
serverSock.bind(('',1122)) # 1024 이후의 포트번호 이전은 많은 서버들이 이미 사용중
serverSock.listen()

#menuList="메뉴: [추가:a]"
In [6]:
 #   #commThread = threading.Thread(target=comm,args=(clientSock,addr))
 #   #commThread.start()
 #   commThread = ServerCommThread(clientSock, addr)
 #   commThread.start()
 #   로 교체한부분
import threading
class ServerCommThread(threading.Thread):
    def __init__(self,sock, addr):
        threading.Thread.__init__(self)
        self.sock=sock
        self.addr=addr
        self.menuList="[목록:s] [추가:a] [검색:f] [수정:u] [삭제:d] [종료:x] --->"
        
    def run(self):
        msg =self.menuList
        self.sock.send(msg.encode('utf-8')) #바이트 단위로 전송됨(문자열 이외도 가능) 클라이언트가 수신상태여야 수신 가능하다
        userMenu=self.sock.recv(1024).decode('utf-8') #이용자가 선택한 메뉴
        print("userMunu : "+userMenu)
        if userMenu=='a':
            self.add()
        elif userMenu=='s':
            self.show()
        elif userMenu=='f':
            self.find()
        elif userMenu=='u':
            self.update()
        elif userMenu=='d':
            self.delete()

    userList=[]
    def load(self):
        with open('/Users/lucas/test/userList.pickle','rb') as file:
                return pickle.load(file)
    def save(self,userList):
        with open('/Users/lucas/test/userList.pickle','wb') as file:
            pickle.dump(userList,file)
            print('서버측 파일에 저장')
        
    def add(self):
        msg="번호 이름 전화 이메일:"
        self.sock.send(msg.encode('utf-8'))
        user_bytes = self.sock.recv(1024*10)
        userObj=pickle.loads(user_bytes)
        print('서버에 전달된 데이터:',userObj)
        userList=self.load()
        userList.append(userObj)
        for users in userList:
            print(users)
        self.save(userList)

    def show(self):
        loadList=self.load()
        pickleList=pickle.dumps(loadList)
        self.sock.send(pickleList)
        
    def find(self):
        msg="찾으실 회원 번호:"
        self.sock.send(msg.encode('utf-8'))
        keyword = self.sock.recv(1024).decode('utf-8')
        finding = User(keyword)
        userList=self.load()
        for user in userList:
            if (user.__eq__(finding)):
                res = user.getStr()
                self.sock.send(res.encode('utf-8'))
        
    def update(self):
        msg="수정하실 회원 번호:"
        self.sock.send(msg.encode('utf-8'))
        keyword = self.sock.recv(1024*10).decode('utf-8')
        finding = User(keyword)
        userList=self.load()
        idx=userList.index(finding)
        self.sock.send("수정하실 정보입력: 번호 이름 전화번호 이메일".encode('utf-8'))
        user_bytes = self.sock.recv(1024*10)
        updateUser=pickle.loads(user_bytes)
        userList[idx]=updateUser
        self.save(userList)         
        self.sock.send("수정완료".encode('utf-8'))

    def delete(self):
        msg="삭제하실 회원 번호:"
        self.sock.send(msg.encode('utf-8'))
        keyword = self.sock.recv(1024*10).decode('utf-8')
        finding = User(keyword)
        userList=self.load()
        idx=userList.index(finding)
        self.sock.send("정말로 삭제할까요?(y/n)".encode('utf-8'))
        answer = self.sock.recv(1024).decode('utf-8')
        if (answer=='y'):
            userList.remove(finding)
        self.save(userList)         
        self.sock.send("삭제완료".encode('utf-8'))
        
In [ ]:
'''
def comm(sock,addr):
    # 문자열 송신 , 계속해서 접속자를 받아주어야 한다. 따라서 Thead+while
    msg = menuList
    sock.send(msg.encode('utf-8')) #바이트 단위로 전송됨(문자열 이외도 가능) 클라이언트가 수신상태여야 수신 가능하다

    userMenu=sock.recv(1024).decode('utf-8') #이용자가 선택한 메뉴
    print("userMunu : "+userMenu)
    if userMenu=='a':
        msg="번호 이름 전화 이메일:"
        sock.send(msg.encode('utf-8'))
        user_bytes = sock.recv(1024*10)
        userObj=pickle.loads(user_bytes)
        print('서버에 전달된 데이터:',userObj)
        with open('/Users/lucas/test/userList.pickle','wb') as file:
            pickle.dump([userObj],file)
            print('서버측 파일에 저장')
    else:
        print("Debug"+userMenu)
'''
while True: #   1. 중지 되지 않는 서버 작성 * 무한히 클라이언트 대기 기능
    print('서버 대기중...') #실헹하면 보안경고창 표시됨, 액세스 허용
    clientSock, addr = serverSock.accept() #튜플 리턴 (clentSock,addre)생략 [주소]
    print(str(addr),'클라이언트 접속됨')
    #commThread = threading.Thread(target=comm,args=(clientSock,addr))
    #commThread.start()
    commThread = ServerCommThread(clientSock, addr)
    commThread.start()
    
# time.sleep(1) #기다림 없이 서버가 끝나버려서 수신이 안될수 있다.추후 무한루프로 인해 삭제할것임

print('서버 종료')
 
서버 대기중...
 
Exception in thread Thread-9:
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/var/folders/4m/y331ttm54b73h77wmw6sl8c80000gn/T/ipykernel_5979/3762507346.py", line 18, in run
BrokenPipeError: [Errno 32] Broken pipe
 
userMunu : 
userMunu : 
userMunu : 
('127.0.0.1', 50763) 클라이언트 접속됨
서버 대기중...
userMunu : s
('127.0.0.1', 50764) 클라이언트 접속됨
서버 대기중...
userMunu : f
('127.0.0.1', 50765) 클라이언트 접속됨
서버 대기중...
userMunu : a
 

Client

In [1]:
class MsgObj:
    def __init__(self,num,msg):
        self.num=num
        self.msg=msg
    
    def __str__(self):
        return f'{self.num}\t{self.msg}'
In [2]:
class User:
    def __init__(self,num,name=None,phone=None,email=None):
        self.num=num
        self.name=name
        self.phone=phone
        self.email=email
    def __str__(self):
        return f'{self.num}\t{self.name}\t{self.phone}\t{self.email}'
    def __eq__(self):
        return True if self.num==other.num else  False
In [10]:
#Client
from socket import *
import pickle
import time

clientSock=socket(AF_INET, SOCK_STREAM)
clientSock.connect(('127.0.0.1',1122)) # 127.0.0.1 -> 현재 컴퓨터 (host)


# 문자열 수신
menuList = clientSock.recv(1024) # 한번에 가져올 바이트 수 (부족하면 반복호출해야 함)
userMenu = input(menuList.decode('utf-8')) # 메뉴 보여주기
clientSock.send(userMenu.encode('utf-8')) # 클라이언트가 선택한 메뉴를 서버에 전달
#print(msg.decode('utf-8'))
if userMenu=='a':
    # 오브젝트 직렬화 및 송신
    # 서버측에서 전달된 데이터 : 번호 이름 전화 이메일
    itemsToInput=clientSock.recv(1024).decode('utf-8')
    sIn = input(itemsToInput)
    [num,name,phone,email]=sIn.split()
    uInfo=User(num,name,phone,email)
    user_bytes=pickle.dumps(uInfo)
    clientSock.send(user_bytes)
elif userMenu=='s':
    usersPickle=clientSock.recv(1024)
    users=pickle.loads(usersPickle)
    for user in users:
        print(user)
elif userMenu=='f':
    msg = clientSock.recv(1024).decode('utf-8')
    kbd=input(msg)
    clientSock.send(kbd.encode('utf-8'))
    res = clientSock.recv(1024).decode('utf-8')
    print(res)
elif userMenu=='u':
    msg = clientSock.recv(1024).decode('utf-8')
    kbd=input(msg)
    clientSock.send(kbd.encode('utf-8'))
    msg = clientSock.recv(1024).decode('utf-8')
    kbd=input(msg)
    [num,name,phone,email]=kbd.split()
    uInfo=User(num,name,phone,email)
    user_bytes=pickle.dumps(uInfo)
    clientSock.send(user_bytes)
    msg = clientSock.recv(1024).decode('utf-8')
    print(msg)
elif userMenu=='d':
    msg = clientSock.recv(1024).decode('utf-8')
    kbd=input(msg)
    clientSock.send(kbd.encode('utf-8'))
    msg = clientSock.recv(1024).decode('utf-8')
    kbd=input(msg)
    clientSock.send(kbd.encode('utf-8'))
    msg = clientSock.recv(1024).decode('utf-8')
    print(msg)


print('클라이언트 종료')
 
[목록:s] [추가:a] [검색:f] [수정:u] [삭제:d] [종료:x] --->a
 
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Input In [10], in <module>
     15 if userMenu=='a':
     16     # 오브젝트 직렬화 및 송신
     17     # 서버측에서 전달된 데이터 : 번호 이름 전화 이메일
     18     itemsToInput=clientSock.recv(1024).decode('utf-8')
---> 19     sIn = input(itemsToInput)
     20     [num,name,phone,email]=sIn.split()
     21     uInfo=User(num,name,phone,email)

File /opt/homebrew/lib/python3.9/site-packages/ipykernel/kernelbase.py:1075, in Kernel.raw_input(self, prompt)
   1071 if not self._allow_stdin:
   1072     raise StdinNotImplementedError(
   1073         "raw_input was called, but this frontend does not support input requests."
   1074     )
-> 1075 return self._input_request(
   1076     str(prompt),
   1077     self._parent_ident["shell"],
   1078     self.get_parent("shell"),
   1079     password=False,
   1080 )

File /opt/homebrew/lib/python3.9/site-packages/ipykernel/kernelbase.py:1120, in Kernel._input_request(self, prompt, ident, parent, password)
   1117             break
   1118 except KeyboardInterrupt:
   1119     # re-raise KeyboardInterrupt, to truncate traceback
-> 1120     raise KeyboardInterrupt("Interrupted by user") from None
   1121 except Exception:
   1122     self.log.warning("Invalid Message:", exc_info=True)

KeyboardInterrupt: Interrupted by user

 

'주말⇞코딩' 카테고리의 다른 글

장바구니 만들기中  (0) 2022.01.31
mode2 C.R.U.D. sql을 연동한 로그인 기능  (0) 2022.01.09
자바) 메모장  (0) 2022.01.02
자바 정리_ver.0.3  (0) 2022.01.01
자바) 제비뽑기 / 배열이름 검색  (0) 2021.12.26
Comment