멀티쓰레드 C언어 소켓 프로그래밍 문의
안녕하세요
이번에 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,
write(cli_sockfd[2], buffer, strlen(buffer));
//각 클라이언트[1],[2],[3]에게 값 반환
getchar(); // 이 줄을 첨가해서 실행해 보세요.??
}
에고..
첨가해도 오류가 해결 되지 않네요.ㅜㅜ
왜 클라이언트 1만 값이 전달되지 않을까요,..
실행 결과를 (터미널 4개)
실행 결과를 (터미널 4개) 올려주세요.
---
혹시나 다시 봐도, 현재 소스로는 volatile을 사용할 여지 조차도 없어 보이는데 말입니다.
저도 궁금하네요..;;
컴파일이 안되는 환경인지라 꼼꼼하게 보고있는데요..
몇번을 봐도 클라이언트 1만 값을 못받아올만한 부분은 코드상으로는 없어 보입니다.
지금 코드를 보면 result를 초기화하지 않아서 쓰레기값이 들어가는 문제는 발생할듯 싶은데요.
쓰레기값이라도 받아와야지.. 서버로부터 값을 받지 못하지는 않을텐데... 거참...;;
result 가 전역변수인데 ;; 멀티쓰레드로 돌리면
result 가 전역변수인데 ;; 멀티쓰레드로 돌리면 (드문 확률이긴 하지만) 연산이 충돌나지 않을까요
integer 연산이 atomic 을 지원하는지 윗분말처럼 volatile 을 해야하는 지 쓸데없는 걱정인지 몰라도
result+=val ; 앞뒤에 lock 이나 sleep(0) 이라도 걸어두시는게 어떨지요 ;;
-----
안녕하세요 소프트웨어 공학센터 장원석 책임입니다.
http://www.software.kr
댓글 달기