1

자바에서 클라이언트 - 서버 애플리케이션을 구현하려고합니다. 클라이언트와 서버는 TCP를 통해 서로 통신합니다. 모든 클라이언트 메시지를 처리하는 중앙 서버는 하나뿐입니다.디자인 패턴 : 클라이언트 - 서버

통신용으로 RMI를 사용하지 않고 TCP 소켓과 통신하며 클라이언트는 서버를 통해 다른 클라이언트와 통신 할 수 있습니다. 즉, 서버가 클라이언트 A에서 클라이언트 B로 메시지를 전달합니다.

이제 여기에 앉아서 서버 응용 프로그램을 설계하는 방법을 알아 내려고 시도하십시오.

그래서 서버는 항상 연결되지 않은 연결을 수신 대기합니다. 괜찮아. 모든 새로운 클라이언트가 서버에 연결되면 (전화 접속), 서버는 새로운 소켓을 만들고 스레드를 사용하여 동시에 작동하게합니다.

모든 사용자는 클라이언트를 사용하며 모든 클라이언트는 사용자 이름과 비밀번호로 인증되어야합니다.

클라이언트에 대한 소켓 연결을 저장/처리하는 디자인 패턴을 서버에서 검색합니다.

첫 번째 아이디어는 Map이 포함 된 ClientManager라는 큰 Singleton 개체를 만드는 것이 었습니다. 따라서 Server는 ClientManger.getSocketBy (username)와 같은 것을 호출하여 원하는 User (Client)의 Socket을 가져올 수 있습니다.

은 expample를 들어 클라이언트 B.

에 클라이언트 A에서 메시지의 "전달"을 해결할 수 : 사용자 A (클라이언트 A)가 사용자 B (클라이언트 B)에게 메시지를 보내드립니다. 따라서 서버는 사용자 A (클라이언트 A)로부터 메시지를 받고 ClientManager.getSocketBy (사용자 B)를 호출하여 통신 소켓을 사용자 B에게 가져온 다음이 소켓을 통해 메시지를 보냅니다.

하지만 그런 일을위한 좋은 디자인이 될 수 있기 때문에 서버 측이 "디자인"간단한 날 것 같다, 등

이벤트 같은 누락 메신저, 관찰자 ​​또 다른 가능성은 던질 수 Socket.send() 메서드를 직접 호출하는 사용자 B 소켓 연결 instad를 처리하는 스레드에 대한 이벤트.

그러나 더 나은 방법이있을 ...

당신이 추천 할 수있는 디자인 패턴이 같은 것을 구현하는 일반적인 방법이 있나요

? Im 인스턴트 메신저 서버가 이것을 구현하는 방법을 궁금해한가요?

그런데 인스턴트 메신저를 구현하지 않고 확장 성은 서버와 통신하는 클라이언트가 1000 명이 아니기 때문에 가장 중요하지 않습니다. 깨끗한 소프트웨어 디자인이 더 중요합니다.

Im은 통신을 위해 자체 프로토콜 (xml 기반)을 구현합니다. 방법/디자인 패턴을 개체에서 프로토콜을 래핑하는 방법 또는 거기에 아무것도 할 수있는 (소프트웨어 아키텍처보기에서 제외) 문자열/xml 구문 분석 excepted?

답변

2

내 생각에는 두 가지 질문이 있습니다.

첫 번째는 라우팅에 사용할 "디자인 패턴"과 관련됩니다. 당신은 당신이하고있는 것을 지적했지만, 너무 단순하다고 말하는 것 이외에 경험하고있는 (또는 경험할 것으로 예상되는) 문제를 나타내지는 않았습니다. 패턴은 일반적인 문제를 해결하는 일반적인 방법이지만 너무 단순한 프로그램은 패턴을 본 적이없는 것입니다.

두 번째 질문은 프로토콜을 사용하는 클라이언트로부터 프로토콜 구현을 분리하는 것에 관한 것입니다. 지금 은 좋은 질문이며 꼭해야 할 일입니다. To, From, Content 등과 같은 필드를 노출하는 Message 객체를 만들려고합니다. 서버는 원시 xml 데이터를 메시지 객체의 팩터 리 역할을하는 일종의 파서로 전달해야합니다.

Message msg = protocol.CreateMsg(byte[] xmlBuffer) 

각 TCP/IP 포트에 다른 하나를 할당하거나 기본 프로토콜로 시작하고 클라이언트와 서버가 서로 다른 프로토콜을 협상함으로써 추가 프로토콜을 지원할 수 있습니다.

EDIT1 : 나는 솔직히 말해서, 사용자에 소켓을 매핑 할 것

. 나는 사용자와 의사 소통하는 방법을 객체 (아마도 연결 또는 채널)로 추상화합니다. 그런 다음 TcpConnection 또는 CorbaConnection 등으로 Connection을 서브 클래 싱합니다. 이상적으로 당신은 다음과 같은 것을하고 있습니다 :

string destUserId = msg.To; 사용자 destUser = UserManager.Find (destUserId); 연결 conn = destUser.Connection; if (conn! = null) conn.Send (msg);

연결 또는 프로토콜 구현에 대한 언급이 없음을 유의하십시오.

+0

그래서 "해독 패턴"에서 실행하고 싶지 않아 ... 예를 들어, User를 Socket으로 매핑하는 Singleton ClientManager는 나에게 이상한 소리를 내고, 그러한 중앙 객체를 가지려면 더 좋은 방법이 있어야합니다 ... 다른 프로젝트가 어떻게 될지 정말보고 싶습니다. 그런 식으로 구현하십시오 ... – sockeqwe

+0

편집을 추가했습니다. 사용자에게 소켓을 단단히 묶고 싶지 않다는 것에 동의합니다. – tcarvin

+0

Connection에 대한 추상화는 반드시 사용해야합니다. Im UserManager와 같은 중앙 클래스가 좋은 아이디어인지 확실하지 않지만 솔직히 말해서 나는 대안을 모른다. 너는 어떤 것을 알고 있니? 사용자에게 연결이 있거나 연결이 있어야 사용자가 있어야합니까? 나는 Connection c = ConnectionManager.find (destUserId)를 사용해야한다; 또는 UserManager.find (destUserId)를 설명하는 방법; 연결 c = UserManager.find (destUserId) .getConnection(). 사용자가이 방법으로 액세스 할 수없는 정보를 포함 할 수 있기 때문에 보안상의 이유로 Connection에 매핑하는 것이 더 나을 수도 있습니다. – sockeqwe

1

서비스 로케이터 패턴을 사용해 보셨습니까? 그러나 Java는 이미 핵심에서 수행중인 작업을 구현하고 왜 "다시 구현할 것인가"를 구현합니다. RMI를 선호하지 않고 이나 ICE과 같은 TCP/UDP 기반 프레임 워크 중 하나를 사용할 수 있으며이 배포 응용 프로그램을 실제로 구축하는 데 도움이됩니다.

+0

답변 해 주셔서 감사합니다.하지만 CORBA, RMI 또는 ICE와 같은 기술을 사용할 수 없습니다. 그리고 내 질문은 어떻게 서버 측에서 자신의 통신 채널 (소켓, RMI, ICE, 또는 뭐든간에) 사이의 매핑을 설계하는 것입니다 – sockeqwe

관련 문제