간단한 udp chat 프로그램에서...

narmi75의 이미지

안녕하세요.
UDP 챗 프로그램을 해보는 중인데요.
내 pc의 ip와 port를 설정하고 bind()한 후 접속할 상대방의
ip와 포트번호를 설정하고 fork()함수를 사용하여 sendto()와
recvfrom()을 구현했습니다. 그런데 구현이 안되네요.
같은 pc에서 프로그램을 두번 실행시켜서..실행해보면..에러는
없는데...서로 주고 받질 못하네요.참고로..udp sendto()만 해주는
프로그램으로 실행해서..붙이면..recvfrom()은 잘 됩니다.
두서없이 적어서 이해가 가실지요.참고로.소스도 올려봅니다.

#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>

#define MAXBUFLEN 100
#define escapechar "exit"
#define TRUE 1

int main()
{
int sockfd, csockfd;
struct sockaddr_in their_addr, my_addr; /* connector's address information */
int addr_len, rnumbytes, snumbytes;
char saddr[4], sport[2], mysport[2];
char sbuf[MAXBUFLEN], rbuf[MAXBUFLEN];
pid_t pid;

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}

printf("My Config...\n");
printf(" Port : ");
scanf("%s",&mysport);

my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(atoi(mysport)); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)))
{
perror("bind");
exit(1);
}

printf("Server Config...\n");
printf(" IP : ");
scanf("%s",&saddr);
printf(" Port : ");
scanf("%s",&sport);

their_addr.sin_family = AF_INET; /* host byte order */
their_addr.sin_port = htons(atoi(sport)); /* short, network byte order */
their_addr.sin_addr.s_addr = inet_addr(saddr);
bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */


if((pid = fork()) < 0)
{
printf("fork error\n");
exit(0);
}
else if ((pid = fork()) > 0)
{
while(fgets(sbuf, MAXBUFLEN, stdin) != NULL)
{
if ((snumbytes=sendto(sockfd, sbuf, strlen(sbuf), 0, \
(struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
{
perror("sendto");
exit(1);
}

if (strstr(sbuf, escapechar) != NULL)
{
printf("Goodbye!\n");
break;
}
printf("sendto syntax\n");
//printf("sent %d bytes to %s\n",numbytes,inet_ntoa(their_addr.sin_addr));
}
}

else
{
while(TRUE)
{
addr_len=sizeof(struct sockaddr);
if ((rnumbytes = recvfrom(sockfd, rbuf, MAXBUFLEN, 0, \
(struct sockaddr *) &their_addr, &addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}
rbuf[rnumbytes] = '\0';

if (strstr(rbuf, escapechar) != NULL)
{
printf("Disconnected by host..!\n");
break;
}
printf(" %s",rbuf);
}
}
close(sockfd);
return 0;
}
[/code]
stoneshim의 이미지

지금 소스를 훑어보니까

(1) socket open.
(2) bind to local port
(3) fork

(parent)
미리 open된 socket에 sendto()

(child)
미리 open된 socket에서 recvfrom()

이런 방식으로 짜신것으로 보이네요..

udp 프로그램은 대개

서버에서 socket open, bind to local port, recvfrom(), (보내기로약속했으면) client(recvfrom에서 알려줌)에게 받은 데이터에 대한 응답을 sendto() 하고
클라이언트에서 socket open, sendto(), (받기로 약속했으면)recvfrom() 합니다.

지금의 테스트 프로그램은 서버측 소켓을 사용하여 클라이언트가 recvfrom()을 하고, 동일한 소켓에 서버가 sendto() 하는 형태로... 좀 이상합니다.

원하시는 구조가 어떤 것인지 자세히 설명해주세요.

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

narmi75의 이미지

먼저 물어봐야 할것을 물어보지 않았네요.
제가...간단한 tcp chat(server/client)을 작성해보고 udp로도 같은 기능을 하는 chat 프로그램을 짜려고 했습니다. udp로 작성하려다 보니 서로 커넥션이 이루어진 상태에서 메세지를 주고 받는 tcp프로그램에 비해 udp는 어떻게 해야할지 생각하다가 결국..udp특성상 결국 서버와 클라이언트가 동시에...동작되어야 하지 않나 하는생각에...짧은 지식으로 이렇게 하면 되지 않을까라고 해보았는데, 저또한 이상한 것은 같으면서 더이상 진행하기가 어려워져서요. 먼저 제가 구현하고자 하는 바가 udp에서 가능한 메커니즘인지가 궁금하네요.

stoneshim의 이미지

제가 파악하기로는 원하시는 chatting 프로그램의 모델은

chatting server가 별도로 존재하면서 chatting client가 서버에 접속하여 자신의
buddy list 등을 받아오고 buddy에게 메시지를 전송하는 이러한 모델이 아니고

하나의 pc에 설치되는 chatting module에서 chatting server와 chatting client의
기능을 모두 구현하는 모델로 보입니다.

이것을 udp로 구현한다면... buddy list는 클라이언트 pc에 저장이
될테구요(음... buddy들이 유동ip를 쓴다면 문제가 되겠네요. 여기선 고정ip를
사용한다고 가정합니다.)

하나의 process로 구성한다고 할때 module이 구동되면

1. client에 저장된 파일에서 buddy list 가져오기( buddy list에는 buddy들의
이름과 ip 정보 정도가 저장되겠지요.)

2. udp socket open.

3. bind to local port(포트번호는 약속이 되어있을겁니다)

4. 사용자 입력과 udp socket을 polling(UNIX계열에서는 select,나 poll 을 사용하면 될테고, windows계열에서는 waitformultipleobject()를 사용하시면 될겁니다)

5-1. 사용자가 특정 buddy에게 메시지를 보내는 입력을 하면 해당 buddy ip주소의 해당 port로 sendto();

5-2. 다른 chatting 프로그램에서 이쪽으로 sendto();하여 udp socket이 readable 하게 되면 recvfrom(); 으로 내용을 받아 화면에 뿌려줌.

이정도의 순서로 진행되지 않을까 싶습니다.

원하시는 대답이 되셨을지 모르겠네요.

그럼 잘 만들어 보시길...

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

댓글 달기

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