멀티쓰레드 C언어 소켓 프로그래밍 문의

wflore의 이미지

안녕하세요
이번에 C언어로 다중 클라이언트 접속 가능한 서버를
Thread를 혼자 공부 후, 코딩을 짜고 있는 학생입니다.

동작과정은
서버는 3개의 클라이언트로부터 int 값을 1개씩 받고,
받은 int 값을 result 변수에 모두 합하여,
각 클라이언트로 동시에 다시 반환해주는 것을 연습하고 있습니다.~

-서버의 내용-

#include
#include
#include
#include
#include
#include
#include
#include

#define MAXLINE 1024

int result;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *myFunc(void *arg)
{
int val = 0;
int clisockfd;
int readn, writen;
char buf[MAXLINE];
clisockfd = *((int *)arg);
readn = read(clisockfd, buf, MAXLINE);
if(readn <= 0)
{
perror("Read Error");
return NULL;
}
val = atoi(buf);
result += val;
printf("%d\n", result);
}

void error(char *msg){
perror(msg);
exit(1);
}

int main(int argc, char *argv[]){
int sockfd, newsockfd, portno = 8888, clilen, th_id, status, count_cli = 0;
int cli_sockfd[3];
pthread_t thread_t[3];
char buffer[MAXLINE];
struct sockaddr_in serv_addr, cli_addr;
int n;
int data;

printf("using port #%d\n", portno);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
error(const_cast("ERROR opening socket"));
}

bzero((char *)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))<0){
error(const_cast("ERROR on binding"));
}
if(listen(sockfd, 5) == -1){
error(const_cast("ERROR on binding"));
}
clilen = sizeof(cli_addr);

while(1)
{
if((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen)) < 0){
error(const_cast("ERROR on accept"));
}
cli_sockfd[count_cli] = newsockfd;
//값 반환을 위해, 소켓fd를 저장해 두기.

printf("client %d's sock_id : %d\n", count_cli+1, cli_sockfd[count_cli]);
th_id = pthread_create(&(thread_t[count_cli]), NULL, myFunc, (void *) &newsockfd);
if(th_id != 0)
{
perror("Thread Create Error");
return 1;
}
pthread_join(thread_t[count_cli], (void **)&status);
count_cli++;
if(count_cli == 3){
break;
}
}

sprintf(buffer, "%d\n", result);
printf("%s\n", buffer);
write(cli_sockfd[0], buffer, strlen(buffer));
write(cli_sockfd[1], buffer, strlen(buffer));
write(cli_sockfd[2], buffer, strlen(buffer));
//각 클라이언트[1],[2],[3]에게 값 반환

}

-클라이언트[1],[2],[3] 내용-
=> 단순하게 값만 전달하고 read하는 기능입니다.

-실행결과-
예로 8,9,10을 각 클라이언트가 전달하면
서버가 값을 잘 합쳐서 27을 만든 후,
클라이언트에 배분을 하는데요~

클라이언트[2],[3]은 값 27을 잘 받는데
클라이언트[1]은 값을 서버로부터 못 가져오더군요.ㅜㅜ

혼자 공부해보고 연습중이라, 이부분이 계속 막히는데
여기서 무슨 에러가 있는 지 알수 있을까요??

익명 사용자의 이미지

write(cli_sockfd[2], buffer, strlen(buffer));
//각 클라이언트[1],[2],[3]에게 값 반환

getchar(); // 이 줄을 첨가해서 실행해 보세요.??

}

wflore의 이미지

첨가해도 오류가 해결 되지 않네요.ㅜㅜ
왜 클라이언트 1만 값이 전달되지 않을까요,..

익명 사용자의 이미지

실행 결과를 (터미널 4개) 올려주세요.
---
혹시나 다시 봐도, 현재 소스로는 volatile을 사용할 여지 조차도 없어 보이는데 말입니다.

익명 사용자의 이미지

컴파일이 안되는 환경인지라 꼼꼼하게 보고있는데요..
몇번을 봐도 클라이언트 1만 값을 못받아올만한 부분은 코드상으로는 없어 보입니다.

지금 코드를 보면 result를 초기화하지 않아서 쓰레기값이 들어가는 문제는 발생할듯 싶은데요.
쓰레기값이라도 받아와야지.. 서버로부터 값을 받지 못하지는 않을텐데... 거참...;;

jos77의 이미지

result 가 전역변수인데 ;; 멀티쓰레드로 돌리면 (드문 확률이긴 하지만) 연산이 충돌나지 않을까요
integer 연산이 atomic 을 지원하는지 윗분말처럼 volatile 을 해야하는 지 쓸데없는 걱정인지 몰라도
result+=val ; 앞뒤에 lock 이나 sleep(0) 이라도 걸어두시는게 어떨지요 ;;

-----
안녕하세요 소프트웨어 공학센터 장원석 책임입니다.
http://www.software.kr

댓글 달기

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