accept 함수에서....

miso의 이미지

제가 지금 서버를 만들고 있는데요...
socket과 pthread를 사용해서요....
그런데....
이상하게 packet을 주고 받기를 못하는 거예요...
그래서.. 이것 저것.... 하다가 알아 낸것이...
accept 함수에서 소켓을 만들잖아요.. 그런데.. 이 소켓이 계속 같은 소켓만 만드네요..

UserSocket = accept(m_ListenSocket, (struct sockaddr *)&UserAddr, (socklen_t*)&nLen);
printf("socket : %u\n", UserSocket);

에서 socket을 printf함수로 찍어 봤던니... 계속 같은 숫자만 찍네요..
window에서는 다른 숫자를 찍어는요...
linux에서는 원래 같은 숫자를 찍나요...
왜 이런 현상이 나타나는지.. 제가 뭘 잘 못 했는지..

제가 pthread를 써서 클라이언트가 접속할때마다 쓰레드를 생성하는데...
이것때문에 세그먼트 디폴트가 나오는 것 같은데...
해결 방법 좀 알려주세요...
일주일째 이것 때문에 일도 못하고 있습니다..
이해가 가기전에 해결해야하는데...

process의 이미지

음..... 소스가 좀 더 있어야 확인이 가능할거 같은데요....

소켓 만든부분 부터 소스를 좀더 올려 주시면...

.
.

제가 그렇게 구현한적이 있거든요.... 잘 동작 합니다.

miso의 이미지

소스는 제가 만든 소스가 아니라 올릴 수는 없고요....
일단 설명을 다시 드리면..

A라를 클래스가 있습니다....
그 클래스를 main 함수에서 선언하고 사용합니다.
A의 Start함수가 있는데...
Start함수에서...
Listen 소켓을 생성하고...
bind하고... listen 한다음...

Start 함수의 일부분입니다.

if (bind(m_ListenSocket, (struct sockaddr *)&ServerAddr, 
	sizeof(struct sockaddr)) == -1) {
	close(m_ListenSocket);
	printf("bind error\n");
	return FALSE;
}

// Set the socket to listen
if (listen(m_ListenSocket, SOMAXCONN) == -1) {
	close(m_ListenSocket);
	printf("listen error\n");
	return FALSE;
}

// Create the listening thread
nThread = pthread_create(&m_ListenThread, NULL, ListenThread, this);
if (nThread) {
	close(m_ListenSocket);
	printf("create thread error.\n");
	return FALSE;
}

Start 함수에서..
쓰레드를 생성하고... 그다음에.. ListenThread 함수에서...
accept 함수를 부르는데요...

제가 다시 이것 저것 해보니까...
ListenThread에서.. 다른 쓰레드를 또 생성하거든요...
클라이언트가 접속 할때 마다...
근데...
쓰레드를 생성하는 부분을 빼면.. accept가 다른 소켓을 생성하는데...
이 쓰레드 생성하는 부분만 넣으면.. 같은 소켓을 계속 생성하는 것 같습니다...

그리고.. 쓰레드를 생성하다가 세그먼트 디폴트를 발생하고 그냥 죽어 버리
네요...
왜 그런지....

*^^*

choissi의 이미지

ListenThread에서 accept후에... 실제 클라이언트와
접속을 담당하는 쓰레드를 생성하신다고 했는데 (이 실제
접속을 담당하는 쓰레드를 클라이언트쓰레드라고 하겠습니다.)

제 생각에는 클라이언트쓰레드가 제대로 동작을 못해서
인듯 싶네요... accept하자 마자 프로그램에서 close처리 해버리면
새로운 클라이언트가 와도 계속 같은 fd가 생성되겠죠..

fd를 잘 넘겨 받았는지 쓰레드에서 체크해보세요
그리고 쓰레드에서 fd닫는 루틴이 있으면 거기에 로그좀 찍어 보구요..

실제적인 작업은 쓰레드가 다하는데,
쓰레드 소스를 봐야 머가 잘못인지 알수 있겠네요..

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

miso의 이미지

여러가지 테스트 결과 pthread에 문제가 있는 것 같아요...

그래서 다음과 같이 이것 저것 빼고 제가 구현한 소스에서.....
쓰레드 생성하는 부분만 간단하게 짜 보았습니다...
소스는 다음과 같습니다.

#include <pthread.h>
#include <stdio.h>


void *ThreadProc(void *pData);

void main()
{
	int i, nThread;
	pthread_t testThread;
	
	for (i = 0; i < 20; i++) {
		printf("i : %d\n", i);
		nThread = pthread_create(&testThread, NULL, ThreadProc, (void *)i);
//		pthread_detach(testThread);
		if (nThread) {
			printf("not enough system resources to create a process for the new thread.\n");
			exit(0);	
		}
	}	
}

void *ThreadProc(void *pData)
{
	int index;
	void *retval;
	
	pthread_detach(pthread_self());
	index = (int)pData;
	printf("thread index : %d\n", index);
	pthread_exit(retval);
}

이 소스를 실행해 본결과....
i를 10으로 하든 20으로 하든...
쓰레드가 8개 까지 밖에 생성이 되질 않아요...
그래서 i를 100으로 바꿔서 돌려 봤더니.. 95, 98까지 밖에 생성하지 못 합니다..
왜 그렇건지...
제가 생성하는 것이 무엇이 틀렸는지.. 조언 좀 부탁드립니다..
아직까지.. 해결 못하고... 이러지도 못하고 저러지도 못하고 있습니다...
linux에서 Multi Thread 구현하는 것이 무지 하게 힘이드네요...

늦었지만.. 모두들 새해 복 많이 받으세요.. ^^;;

*^^*

choissi의 이미지

님께서 올린 소스로 제 서버에서 테스트를 해보니
이상없이 동작을 합니다.

제 서버의 환경은 이렇습니다.
wow6.2up에다가 커널업만 해줬습니다.

Linux version 2.4.19 (root@hyuna.zeroin.co.kr) (gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)) #1 금 9월
20 12:10:53 KST 2002

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

miso의 이미지

그럼.. 어떻게 해야 하나요...
제가 window C는 좀 해봤지만.. linux C는 완전 초보라서요...

저의 linux 버전은...
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.95.4/specs
gcc version 2.95.4 20010319 (prerelease)
입니다...

process 생성하는 것이 어려워서.. pthread를 쓰려고 했는데...
어떻게 해결 방법이 없을까요?
wow6.2up에 커널업은 어떻게 해주나요?

*^^*

choissi의 이미지

제가 2.4.x로 업할때 참고한 글입니다.

http://www.wowlinux.com/information/techupview.html?id=47&view=1

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

xfree의 이미지

main thread에서 pthread_join을 호출하지 않았네요

child thread가 생성되고 printf를 실행하기 전에

main thread가 종료되면 어케 될까요??

이해되셨죠??

그럼 즐프~

miso의 이미지

음...
처음에...
pthread_join을 사용해서 만들었습니다..
잘 돌아 가더라고요..
MultiThread로 잘 돌아 가는 줄알았습니다....
근데 좀 이상해서 테스트를 해봤더니...
계속해서 Thread 하나만 가지고 사용하다라고요...
그래서 다중 사용자가 접속하면...
한명이 접속이 끝나고 나서야 그다음 사용자가 결과를 가져가더라고요...
pthread_join이라는 함수가
그 쓰레드가 끝날때 까지 기다리라는 함수라고 하더라고요...
그래서 계속 같은 소켓만 생성하고 객체를 생성하는데 계속 처음에 생성한
객체 하나만 사용하더라고요..
아직도 해결을 못했는데...
제발 좀 누가 알려주세요...

왜 위 소스에서 쓰레드가 개수 만큼 생성이 안돼는지...
MultiThread를 구현 하려면 어떻게 해야하는지 좀 알려주세요..

*^^*

process의 이미지

제가 했었던 것을 지울건 지우고 올립니다....
이런식으로 하는건 아주 잘 되거든요... 커넥션이 하나 맺어질때 마다
쓰레드가 하나씩 생성됩니다.

int main(int argc, char *argv[])
{
	pthread_t tid;
	struct sockaddr_in addr;
	int	sock, new_sock, on = 1;
	pthread_t tid;

	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	signal(SIGCONT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGTERM, term_signal);
	signal(SIGHUP, hup_signal);

	if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
		syslog(LOG_POINFO, "create_socket() : socket() : %m");  exit(1);
	}

	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(DEFAULT_BIND_PORT);
	addr.sin_addr.s_addr = INADDR_ANY;

	if( bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
		syslog(LOG_POINFO, "create_socket() : bind() : %m");  exit(1);
	}

	if( listen(sock, SOMAXCONN) < 0 ) {
		syslog(LOG_POINFO, "create_socket() : listen() : %m");  exit(1);
	}

	for(;;) {
		while( (new_sock = accept(sock, (struct sockaddr *)NULL, NULL)) < 0 ) {
			if( errno == EINTR )
				continue;
			else {
				syslog(LOG_POINFO, "create_socket() : accept() : %m");  exit(1);
			}
		}

		if( pthread_create(&tid, NULL, &run_thread, (void *)new_sock) ) {
			syslog(LOG_POINFO, "pthread_create( run_thread ) : %m");
			close(new_sock);
		}
	}

	close(sock);
	return 0;
}

void *run_thread(void *arg)
{
                int sd;
	pthread_detach(pthread_self());

	sd = (int)arg; // socket fd
////////
여기서 부터 sd를 가지고 read/write를 맘대로 하시면 됩니다
////////
                close(sd);
	return (NULL);
}
miso의 이미지

우선 저에게 소스를 보여 주셔서 감사합니다..

보여주신 소스 방식으로 짜 봤는데요...
제가 클라이언트가 10개 동시 접속해서 쓰레드를 10개 생성하게 했는데요..
6개 까지 생성하고 세그먼트 디폴트를 생성하고 죽어 버려요..

틀린점은..
첫째 signal 함수를 사용하지 않았고요...
둘째 쓰레드 함수에 그러니까.. run_thread 함수에 인자값 arg를 구조체로 넘겨 주겨든요..
구조체에 new_sock을 담아서요...
구조체에는 Class 객체를 두개 가지고 있습니다...

쓰레드 인자 값으로 구조체를 넘겨서 문제가 되나요?
아님 signal 함수를 사용하지 않아서 문제가 되나요?
이유가 뭔지 정말 모르겠습니다..
조언 좀 주세요... ㅜㅜ

*^^*

process의 이미지

흠... 인자로 구조체를 넘기는 건 문제가 안되구요.....

각각 쓰레드에 넘겨지는 구조체는 역시 각각 할당된거겠죠?...
그리고 시그널과 쓰레드가 문제가 많긴하지만... 여기선 별 문제가 안될거 같구요...... segmentation fault 라니.. 문제가 있는건 확실한뎅...ㅡ.ㅡ

일단은 님 시스템에서 쓰레드가 정확히 만들어 지는지 집고 넘어가야 할거 같군요...
님이 작성하신 테스트 코드에 한두줄 추가했습니다.... 이 코드로는 쓰레드가
올바르게 생성되야 할거 같은데요...

#include <pthread.h> 
#include <stdio.h> 
#include <errno.h>
#include <err.h>

void *ThreadProc(void *pData); 

void main() 
{ 
   int i, nThread; 
   pthread_t testThread; 
    
   for (i = 0; i < 5; i++) { 
      printf("i : %d\n", i); 
      nThread = pthread_create(&testThread, NULL, ThreadProc, (void *)i); 
//      pthread_detach(testThread); 
      if (nThread) { 
         //printf("not enough system resources to create a process for the new thread.\n"); 
         if( nThread == EAGAIN )
         	printf("error code: %d\n", nThread);
         //perror("error");
         exit(0);    
      } 
   } 
   
   sleep(10);   
} 

void *ThreadProc(void *pData) 
{ 
   int index; 
   void *retval; 
    
   pthread_detach(pthread_self()); 
   index = (int)pData; 
   printf("thread start index : %d\n", index); 
   sleep(3);
   printf("thread end index : %d\n", index); 
   pthread_exit(retval); 
}
miso의 이미지

먼저 이렇게 답변을 주셔서 정말 감사합니다...
그래도 어려운 상황에서 도와 주시는 분이 있다니 힘이 됩니다.

님께서 써주신 소스로 저의 컴퓨터에서 실행을 해 보았습니다.
쓰레드가 잘 생성이 됩니다...
그런데 문제는 이것을 소켓 생성하는 부분에 넣으면...
즉 sleep이라는 함수를 쓰레드 생성하는 부분에 넣으면...
그러니까...
1월 3일 보여주신 소스에서요...
================
for(;;) {
while( (new_sock = accept(sock, (struct sockaddr *)NULL, NULL)) < 0 ) {
if( errno == EINTR )
continue;
else {
syslog(LOG_POINFO, "create_socket() : accept() : %m"); exit(1);
}
}

if( pthread_create(&tid, NULL, &run_thread, (void *)new_sock) ) {
syslog(LOG_POINFO, "pthread_create( run_thread ) : %m");
close(new_sock);
}

sleep(2); //====> 추가부분
}

===================
넣으면요.. 세그먼트 디폴트는 안나는데요...
계속 같은 소켓을 생성하더라고요...(즉 new_sock의 값이 일정하게 4만 나옵니다.)
그리고 제가 미리 객체를 열개를 생성하는데요..
계속해서 객체 하나만 사용합니다...
만약에 동시 사용자가 100이상이 되면 문제가 되지 않을까요?...
어떻게 해결 방법이 없을까요?...

*^^*

process의 이미지

음... 님의 테스트 코드에 sleep를 넣었던것은 자식 쓰레드들이 모두 끝날때 까지 충분히 기다리기 위해 넣었던거구요.. 제가 올린 코드에 sleep을 주는 건 쫌 문제가 있군요.... accept되고 쓰레드가 만들어지고 2초 전에 그 쓰레드가 종료된다면 2초 후에 accept가 다시 동작 하니까 계속 같은 소켓만 생성이 되겠죠... 객체도 하나만 계속 사용할거구요.....

세그멘테이션 폴트가 나는건 추측건데(소스가 없으니..) 객체들 사용에 있어
충돌이 나서 죽는것 같구요.... 제가 보여드린 소스를 그대로 컴팔해서(약간은 수정..^^) (객체가 포함된 구조체를 넘기지 말고..) 정상적으로 동작을 한다면....

님이 작성하시고 있는 소스에서 각각의 쓰레드들에서 객체들이 사용되는데..
논리적인 문제가 있다고 밖에 말씀드릴수 없을것 같군요....
클래스가 쓰레드들마다 독립적으로 잘 사용되는지 혹시 쓰레드들간 꼬이지는 않는지 살펴보시는게./.... 흠...

miso의 이미지

님의 말씀을 듣고 소스를 하나하나 뜯어 봤습니다...
그랬더니.. 메모리 해제를 안해야 하는 곳에서 메모리 해제를 해서...
그런 현상이 나타나더군요....

정말 감사합니다..
새해 복 많이 받으시고요...
항상 건강하시고 항상 행복하세요... ^^

*^^*

댓글 달기

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