select IPC 미들웨어란?

익명 사용자의 이미지

안녕하세요
제가 생각하는 시나리오를 구현하려면 어떻게 해야 하는가를 여쭈얼 볼려
구 합니다.

내용은 채팅서버와 같구요.
1cli가 컨넷트하면, select을 등록해서 cli_list를 만들고, 그것의 내용
을 내려보내준다.
2 cli는 받은 리스트중 1명만을 선택할 수 있구, 그 상대방을 지정한다.
cli_list_buf[i] 중 i 값으로 지정하게 할려구요.
3 미들서버는 현재의 cli와 cli_list_buf[i] 만이 통신하게끔 채팅proc에
게 두개의 sock_fd 값을 보낸다.
4 이것을 받은 채팅서버는 두 개의 fd를 등록해서 2명만이 채팅하게 한
다.
5 만약 1명이 그만두면, 다시 미들서버로 현재 남아있는 1명의 소켓넘버
를 보내서 cli_list_buf[last]에 등록하게 한다.

여기에서 5번때문에 원래 1개의 프로세스(Middleselect가 되는 프로세스)
에서 fork()나 쓰레드가 불가하다고 생각하거든요.
그래서 cli1-->채팅요청cli2--> Middle==>메세지==>채팅서버
Middle cli1_fd, cli2_fd 가open된 상태에서
cli1 <---------------------------------->채팅서버
cli2 <---------------------------------->채팅서버
이렇게 cli1,2만을 묶어서 통신하게 하다가 상대방이(cli2)죽으면
Middle<==메세지==채팅서버
내용은 fclose(cli2)했구 cli1_fd를 다시 등록해줘

단, 가정은 IP의 값으로 통신은 할 수없구, 오직 sock_fd로만 통신이 가능
합니다 . 연결과 종료는 (client당근이죠^^*) 쪽에서만 먼저 할 수있다.
서버는 채크만 가능하고 select시는 recv값이 -1 , 또는 write시는
SIGPIPE에러가 나오는가를 체크해서 연결이 끊김을 인지한다.

즉,
cli1---> connect (1)---> middle_server
1. select;
2.recv(cli_fd,list);
3.send(cli_fd_list
4.recv(cli_fd_list) 그리고 choose
5 send( 몇번째를 선택)
6.select하고 있다가
cli1이 애기하는군.
cli2를 요구하고.
6 그러면 채팅서버로 socket_fd메세지를 보내자
현재의 cli_fd_buf[]에서 제거하고
단 close는 하지 않는다. 연결이 귾기면 안되고.
채팅서버로 부터 다시 연결메세지를 들으면 다시
cli_fd_list를 내려주어야 하기 때문이다.

6번째 때문에 여기서 fork나 쓰레드를 사용하지 못 하느것 같은데.
제가 잘못 생각하고 있는 것인가요?

현재 돌아가는 채팅서버들은 어떤 구조로 되는지...궁굼합니다.
그리고 자료도 필요하구요..
고수님의 따듯한 손길을 ^^*

PS 참 장황하게 썻네요...죄송..^^*

익명 사용자의 이미지

말씀하신 구조에서도 fork()나 thread 를 사용하실 수 있을 것 같습니다.
일단 제가 이해하기로는,

중간에 말씀하신 미들웨어(?)가 있고,
이 미들웨어에서 채팅할 상대방 두쌍을 짝지은 다음에
실제 채팅은 채팅서버에서 이뤄지게 하고,
어느 한쪽 클라이언트 쪽의 요청에 따라 채팅이 끝난다면
채팅서버 쪽에서 채팅을 하던 사용자는 다시 미들웨어 쪽에 돌아와서
다음 채팅할 상대를 기다리는 구조인데 맞나요?

fork() 로 먼저 얘기를 해 보도록 하지요.
fork() 할 때는 소켓 디스크립터 한쌍을 전달하겠지요?
(아마 fork니까 변수로 전달이 되겠지요?)
그러면 채팅서버는 두 디스크립터 사이에서 select를 하면서
이쪽에서 데이터가 오면 저쪽으로 넘겨주고,
저쪽에서 데이터가 오면 이쪽으로 넘겨주는 일을 할 것이고요,
둘 중의 한 녀석이 연결을 종료한다 하면,
미들웨어 쪽에 정보를 알려줘야 하잖아요?
일단 미들웨어는 어떤 child가 어떤 소켓 디스크립터 쌍을 가지고
채팅을 하고 있다는 것은 알고 있는 상태겠고요
(매번 채팅서버를 fork()할 때마다 이 정보는 보관하고 있어야겠죠)
그러면 채팅서버가 종료하면 parent인 미들웨어는 어떤 채팅서버가
죽었는지 알 수 있잖아요? 그럼 그 채팅서버에서 사용하던 디스크립터도
아니까 이중에서 연결을 끊은 녀석은 리스트에서 제거하고,
그렇지 않은 녀석은 다시 리스트에 넣으면 되겠죠.
어떤 녀석이 연결을 끊었는지는 채팅서버에서는 exit() 값으로
알려주면 될테고요. 미들웨어에서는 wait 에 넘어오는 status 값으로
알아내면 되겠고요.

thread는 fork 보다 훨씬 융통성있는 통신방법을 구사할 수 있기 때문에,
fork 보다 더 쉽게 할 수 있을 것 같고요.

근데, 구상하신 방법은 여러가지 살을 붙여야 할 것 같습니다.

일단, 클라이언트와의 통신시에 너무 저수준의 정보(fd)를 전달하는 것
같고요 (정말 채팅프로그램인가요? 아니면 채팅프로그램처럼 통신을 하는
것이 필요한 프로그램끼리의 통신인가요?), 간단히 생각해보면,
client A 가 client B와 통신하고 싶어서 client B의 소켓번호 5를 지정했
는데, client B는 그 사이 이미 채팅을 마치고 종료해서 나갔고 다른 녀석
이 들어와서 다시 소켓 번호 5번을 할당받았다면 client A는 의도했던
client B가 아니라 다른 client C와 통신을 하게 되는 것이고, 더 나쁠
수 있는 것은 통신 상대가 바뀌었다는 것을 알지 못한다는 것이죠.
그렇다고 client A가 상대를 정할 때가지 client B를 묶어두거나 fd list
를 lock 걸어둘 수도 없는 일이고요.

그외에도 여러가지 고려할 사항이 있을 것 같은데요,
IRC 나 다른 채팅 프로그램을 한번 분석해 보시는 것이 좋을 듯 합니다.

수고하세요,,

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.