스레드 프로그래밍에 대해서...
안녕하셔요. cd, ls, dir, pwd, get명령으로 파일 내용보기를 할 수 있는
서버 프로그램을 만들고 있습니다. fork();로는 잘되게 되었는데
스레드를 사용해서 해볼려고 하는데 잘 안되네요. 일단 서버가 돌고,
클라이언트가 접속해서 cd 명령으로 디렉토리를 바꾸고 해당 명령을
수행도중에 다시 또다른 클라이언트가 접속을 해서 ls 명령을 하면
전에 먼저 접속했던 클라이언트가 cd 명령으로 내린 디렉토리로 이동
해서 작업이 되더군요. ㅜ,.ㅜ; 그럼 첫번째 클라이언트가 다시 cd명령
으로 다른 디렉토리로 이동하면, 두번째 접속한 클라이언트 또한 cd명령
을 내린적이 없는데 첫번째 클라이언트가 이동한 디렉토리에서 위 명령
들이 먹히더군요. 스레드 특성상 공유를 해서 그런것 같은데...
각각의클라이언트끼리 이런 문제가 발생하지 않고 자기만의 디렉토리에서
작업 되도록 어떻게 해야할지... 여러모로 해봤지만, 안되더군요. 이걸 해
결하는 방법이 없을까요? 알고리즘 문젠거 같은데...
즉, 서버가 실행되고 클라이언트가 접속할 때 맨처음 디렉토리를
저장할 수 있게 해서 하면 될것도 같은데... 문제 해결을 못하겠네요.
다음은 소스파일입니다. POSIX 스레드로 구현했습니다.
fcf변수는 디렉토리를 저장할려고 선언한건데... 방법이 아닌것 같네요.
스레드에 관한 문서를 봐도 개념적인 것만 있어서 참고도 못하고 궁금해
죽을꺼 같네요. 스레드 프로그램은 그만 여기서 접어야 하는건지...
#define _REENTRANT
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 4096
#define MODE 0666
#define MAXLINE 1024
// Thread function define
void *ch_function(void *);
char *fcf[4];
int ch_id = 0;
int i = 0;
char filename[30] = {'\0'};
char *escapechar = "quit\n";
int main(int argc, char **argv)
{
int server_fd, newsockfd, client_fd, clilen, num, res;
pthread_t ch_thread;
struct sockaddr_in client_addr, server_addr;
if(argc < 2){
printf("Usage %s TCP_PORT\n", argv[0]);
exit(0);
}
if((server_fd = socket(PF_INET, SOCK_STREAM, 0)) <0){
printf("Client Can't open stream socket\n");
exit(0);
}
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(atoi(argv[1]));
if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof
(server_addr)) < 0){
printf("Server Can't bind local address.\n");
exit(0);
}
printf("Server started.\nWaiting for client...\n");
pthread_setconcurrency(5);
listen(server_fd, 5);
for(;;){
clilen = sizeof(client_addr);
if((client_fd = accept(server_fd, (struct sockaddr *)
&client_addr, &clilen)) != -1){
printf("Server client connected.\n");
}
else{
printf("Server failed in accepting.\n");
exit(0);
}
// Thread creation
res = pthread_create(&ch_thread, NULL, ch_function, (void *)
client_fd);
if(res != 0){
printf("Thread creation failed\n");
exit(0);
}
}
exit(0);
}
void *ch_function(void *arg)
{
int sock_fd = (int)arg;
char sendline[MAXLINE], rbuf[MAXLINE];
int size, k;
void *status;
char *fcf[0];
ch_id = pthread_self();
// fcf[ch_id] = getcwd(NULL, 64);
while(1){
if((size = read(sock_fd, rbuf, MAXLINE)) > 0){
rbuf[size] = '\0';
printf("Request service from client %s\n", rbuf);
if(strncmp(rbuf, escapechar, 4) == 0){
exit(0);
}
if(strncmp(rbuf, "dir", 3) == 0 || strncmp(rbuf, "ls", 2) == 0)
{
dir(sock_fd);
}
if(strncmp(rbuf, "pwd", 3) == 0){
pwd(sock_fd);
}
if(rbuf[0] == 'c'){
printf("%s\n", fcf[ch_id]);
}
if(rbuf[0] == 'g'){
get_filename(rbuf, sock_fd);
}
}
}
close(sock_fd);
pthread_exit(status);
}
dir(int client_fd)
{
char cmd[30] = "/bin/ls -al ";
char dir[20];
char buf[BUF_SIZE];
FILE *ptr;
strcpy(dir, ".");
strcat(cmd, dir);
if((ptr = popen(cmd, "r")) != NULL){
while(fgets(buf, BUF_SIZE, ptr) != NULL){
if(write(client_fd, buf, strlen(buf)) != strlen(buf)){
printf("Server fail in writing.\n");
}
}
pclose(ptr);
}
}
pwd(int client_fd)
{
char pwd[30] = "/bin/pwd";
char buf[BUF_SIZE];
FILE *ptr;
if((ptr = popen(pwd, "r")) != NULL){
while(fgets(buf, BUF_SIZE, ptr) != NULL){
if(write(client_fd, buf, strlen(buf)) != strlen(buf)){
printf("Server fail in writing.\n");
}
}
pclose(ptr);
}
}
cd_dir(char *rbuf, int client_fd)
{
int flag;
int i, k;
if(rbuf[0] == 'c'){
flag = 1;
for(i = 0; i <= strlen(rbuf); i++){
if(rbuf[i] == 'c'){
continue;
}
if(rbuf[i] == 'd'){
continue;
}
if(rbuf[i] == 32){
flag = 1;
break;
}
flag = 0;
}
i = i + 1;
while(rbuf[i] == 32)
i = i + 1;
if(flag == 1 && rbuf[i] != 10){
for(k = 0; k <= strlen(rbuf) - i - 2; k++){
filename[k] = rbuf[i + k];
}
for(k - 2; k <= strlen(filename); k++){
filename[k] = '\0';
}
}
else{
strcpy(filename, rbuf);
}
if(chdir(filename) == -1){
write(client_fd, "Input error -> Usage cd dir_name !!",
strlen("Input error -> Usage cd
dir_name !!"));
}
}
for(i = 0; i <= sizeof(filename); i++)
filename[i] = '\0';
for(i = 0; i <= sizeof(rbuf); i++)
rbuf[i] = '\0';
}
get_filename(char *rbuf, int client_fd)
{
int flag;
int i, k;
char buf[BUF_SIZE];
int fin, n;
FILE *fp;
if(rbuf[0] == 'g'){
flag = 1;
for(i = 0; i <= strlen(rbuf); i++){
if(rbuf[i] == 'g'){
continue;
}
if(rbuf[i] == 'e'){
continue;
}
if(rbuf[i] == 't'){
continue;
}
if(rbuf[i] == 32){
flag = 1;
break;
}
flag = 0;
}
i = i + 1;
while(rbuf[i] == 32)
i = i + 1;
if(flag == 1 && rbuf[i] != 10){
for(k = 0; k <= strlen(rbuf) - i - 2; k++){
filename[k] = rbuf[i + k];
}
for(k - 2; k <= strlen(filename); k++){
filename[k] = '\0';
}
}
else{
strcpy(filename, rbuf);
}
}
fp = fopen(filename, "r");
if(fp == NULL){
printf("Can't open file %s\n", filename);
strcpy(buf, "File is not found - Usage get filename !!");
if(write(client_fd, buf, strlen(buf)) != strlen(buf)){
printf("Server fail in writing.\n");
}
return;
}
while(fgets(buf, BUF_SIZE, fp) != NULL){
if(write(client_fd, buf, strlen(buf)) != strlen(buf)){
printf("Server fail in writing.\n");
exit(0);
}
}
fclose(fp);
for(n = 0; n <= sizeof(filename); n++)
filename[n] = '\0';
for(n = 0; n <= sizeof(rbuf); n++)
rbuf[n] = '\0';
}
Re: 스레드 프로그래밍에 대해서...
소스를 전부 보진 않았구요.
말씀하신,
"스레드 특성상 공유를 해서 그런것 같은데"
이 부분에만 착안해서 스레드 로컬 스토리지
( Thread Local Storage, TLS ) 를 이용하면
어떨지 생각해 봤습니다.
pthread_key_create
pthread_setspecific
pthread_getspecific
pthread_key_delete
스레드마다 개별적인 데이터를 달아줄 수
있습니다.
댓글 달기