스레드 프로그래밍에 대해서...

익명 사용자의 이미지

안녕하셔요. 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';
}

익명 사용자의 이미지

소스를 전부 보진 않았구요.

말씀하신,

"스레드 특성상 공유를 해서 그런것 같은데"

이 부분에만 착안해서 스레드 로컬 스토리지
( Thread Local Storage, TLS ) 를 이용하면
어떨지 생각해 봤습니다.

pthread_key_create
pthread_setspecific
pthread_getspecific
pthread_key_delete

스레드마다 개별적인 데이터를 달아줄 수
있습니다.

댓글 달기

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