네트워크 프로그래밍에 도저히 이해가 잘 가지 않는 부분이 있어 질문 드립니다.

shon0201의 이미지

안녕하세요 네트워크 프로그래밍을 이제 막 시작하여 윤성우의 TCP/IP 책을 보고 있는 중입니다.
여기서 멀티 쓰레드로 서버 클라이언트를 구현 하였는데, 잘 이해가 가지 않는 부분이 있어서 도움을 얻고자 합니다.

우선 Server 소스는

socket()
listen()
bind()
 
while(1)
{
  clnt_sock = accept()
  pthread_create(&thread, NULL, clnt_connection, (void*) clnt_sock);
 
} 

이런식으로 구성되어 client의 요청이 들어올 때마다 쓰레드를 생성하는 구조 입니다.

하지만 clnt_connection 함수에서 Client 전체에 메세지를 보내는 부분이

    for(i=0;i<clnt_number;i++) 
           write(clnt_socks[i], message, len);

이런식으로 전체 client를 for문으로 반복하며 보내는데

각 클라이언트당 쓰레드를 하나씩 생성 하였는데 왜 전체 클라이언트를 검사하며 write를 진행하는 지
도저히 이해가 잘 안됩니다..

그래서 저 반복문을 빼고 clnt_sock 하나에 데이터를 보내 보았더니 어떤 클라이언트 한테는 가고 안 가고를
반복 하더군요.. 혹시 어떤 이유 때문에 이런식으로 코드를 작성 했는지 알 수 있을까요??

미리 감사드립니다..

SungHyun Kim@Google의 이미지

에코서버-자신이 서버에게 메시지를 보내면 그 메시지를 그대로 서버가 보내주는것-를 변형한 코드인데, 그냥 패킷오는대로 다른 접속자에게 다 보내주는 로직입니다.
A를 스래드에 넘겨준 소켓이라하면, 다른 접속자들은 O 라하겠음.
에코서버는 채팅방의 채팅기능처럼 (귀속말 기능아님) A접속자에게 받은 테이터를 다른 O들에게 보내줘야하므로,
cInt_number는 접속자 수(인덱스라 할수있겠네요) 고, 그 인덱스로 실제O접속자를 찾아 message를 다 보내주는겁니다.

각 쓰래드에서 다 똑같은 로직이 돌아갈 것입니다. 이게 실제 서버의 비지니스로직이라고 할수 있구요.
이코드 대신에 다른 내가 원하는 기능을 구현하면 되는것입니다.

예를들어 맨마지막 접속자에게만 보내고 싶다면,
write(clnt_socks[clnt_number-1], message, len);
for를 빼고 요넘만 넣으면 마지막 접속자에게만 메시지를 보내게 됩니다.
모든 접속자O들이 받은 message를 맨마지막 녀석에게 집중적으로 가게 되는거겠죠. (채팅으로 하자면 귀속말기능)

그럼 첫번째 접속자에게만 보낼려면 어떻게 해야할까요?
그럼 짝수 접속자에게만 보낼려면 어떻게 할까요?
등등이 비지니스 로직입니다.
고민해보시고 구현해 보세요.

이해가 되셨을지 모르겠네요.

shon0201의 이미지

그렇다면 pthread_create에서 clnt_sock를 하나 받아 오는데,
Server에서 clnt_sock[] 배열을 다루지 않고 들어온 하나의 소켓 fd에게만 write를 하면 즉,
write(clnt_sock, message, len)을 하면 어떻게 동작하는 원리인지 여쭤봐도 될까요?

각 쓰레드 마다 clnt_sock를 다르게 받아 오는데 왜 굳이 전역변수 배열을 선언해서 client fd를 관리 하는지 잘 이해가 안되어서요..

제가 이렇게 해본 결과로는 들쭉날쭉 클라이언트들이 데이터를 수신했습니다..

SungHyun Kim@Google의 이미지

각기 새로 접속하면 스래드마다 새로운 clnt_sock를 받게 되는겁니다. 그 접속자를 식별할수 있는 고유값이라 보면됩니다.
그리고 그놈에게 받은 메시지를 바로 써주면 그게 바로 에코서버기능입니다.

전역변수 배열을 사용해서 client fd를 관리하는것은 당연히 다른 사용자와 메시지를 주고 받아야하기 때문이죠.
서버에서 어떻게 다른 사용자를 식별할지 고민해 보시기 바랍니다.

아까 예를 들었다시피, 채팅을 상상해보세요.
다른 사용자에게 내 메시지를 전달해야하는데, 그 사람 식별자를 알아야죠?
그 번호가 client fd입니다.

설마, 한 클라이언트 실행화일에서, 같은서버에 몇번 접속하게 만든건 아니겠지요?
한클라이언트에서 서버에 1개의 connection만 맺어서 테스트해보세요.
그 클라이언트를 여러게 띄워놓으면 그게 여러 사용자가 채팅방에 들어가있는 효과가 됩니다.

물론 경우에 따라 한클라이언트(process)가 같은서버에 몇개의 커넥션을 맺을 필요가 있을 수 도 있으나,
이제막 소켓프로그램을 공부하신다면, 책에 있는대로 하시면 될듯싶은데요. 그책이 나쁜책은 아닐듯합니다만.

책대로 하시면됩니다.
그리고 실코드가 어떻게 되어있는 모르니, 더이상 답변드리기 곤란하네요.
클라이언트/서버 코드 다 올려보세요.

익명 사용자의 이미지

설명을 듣고 제 나름대로 이것저것 해보니 제가 헷갈렸던 부분을 이해했습니다.
실 코드까지 올릴 일은 없게 되었지만 감사하다는 말씀은 꼭 드리고 싶네요

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.