C++ 쓰레드 활용 클래스 오버라이딩 문제

MyAbby의 이미지

안녕하세요.

소켓을 클래스화 시켜서 사용하고 싶어 만든 소스가 있습니다.

생성자에서 소켓을 생성하고, bind 해서 듣거나 접속하는 형태로 만들고 있는데, 이벤트 처리가 문젭니다.

onConnection_request()와 onData_receive() 더미함수를 만들어 놓고 자식 클래스에서 오버라이딩 시켜 원하는 처리를 할 수 있게 만들고 싶습니다.

근데 자식클래스에서 오버라이딩을 시켜도 원래 선언했던 더미함수가 실행됩니다... 왜이럴까요. 컴파일러 문제일까요?

연결이 들어오면: start_listen_thread() - *listen_thread_func() - onConnection_request()

이렇게 흘러갑니다. 자식, 부모의 this 값을 찍어보면 모두 동일하게 나오는데 왜 오버라이딩이 되지 않을까요?

class Socket : public UserSocket
{
public: void onConnection_request(const int fd, sockaddr_in addr) {}
public: Socket() : UserSocket("tcp") {}
}

이런 식으로 오버라이딩 시켰습니다...

아래는 클래스 소스구요. 도와줍쇼~

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
 
class UserSocket
{
	public:
		//Call back events
		//콜백 이벤트
		void onData_receive(const int dataSize, const char *data){}
		void onClose(){}
		void onConnection_request(const int fd, const struct sockaddr_in addr){}
		void onAccept(){}
	private:
		//Essential attributes
		//필수 속성들
		int fd = -1; //소켓 번호
		struct sockaddr_in local_addr, remote_addr; //로컬, 상대 주소
		bool sendable = false; //데이터 전송 가능 여부
 
		//Event handlers
		//이벤트 핸들러들
		pthread_t th_listen = 0, th_read = 0;
	public:
		int getFd()
		{
			return fd;
		}
	private:
		static void *listen_thread_func(void *arg)
		{
			class UserSocket us = *(UserSocket*)arg;
			sockaddr_in remote_addr;
			int lst;
			unsigned int SZ_REMOTE_ADDR = sizeof(remote_addr);
			while(true)
			{
				lst = accept(us.getFd(),
						(struct sockaddr*)&remote_addr, &SZ_REMOTE_ADDR);
				if(lst < 0) break;
				us.onConnection_request(lst, remote_addr);
			}
		}
		bool start_listen_thread()
		{
			if(!isGood_to_use()) return false;
 
			if(pthread_create(&th_listen, NULL, listen_thread_func, (void*)this) < 0)
				return false;
			return true;
		}
		static void *receive_thread_func(void *arg)
		{
			class UserSocket us = *(UserSocket*)arg;
			int size;
			char buf[1500];
 
			while(true)
			{
				memset(buf, 0, sizeof(buf));
				size = read(us.getFd(), buf, sizeof(buf));
				if(size <= 0) break;
				us.onData_receive(size, buf);
			}
			us.disconnect();
		}
		bool start_receive_thread()
		{
			if(!isGood_to_use()) return false;
			if(pthread_create(&th_read, NULL, receive_thread_func, (void*)this) < 0)
				return false;
			return true;
		}
	public:
		void lower_str(char *x)
		{
			for(int i=0; x[i]!=0; i++)
			{
				if('A' <= x[i] && x[i] <= 'Z')
					x[i] += 32;
			}
		}
		UserSocket(const char *xProto)
		{
			char *strProto = new char[strlen(xProto) + 1];
			strcpy(strProto, xProto);
 
			int yProto = -1;
			lower_str(strProto);
			if(!strcmp("tcp", strProto))
				yProto = SOCK_STREAM;
			else if(!strcmp("udp", strProto))
				yProto = SOCK_DGRAM;
 
			if(yProto != -1)
				fd = socket(AF_INET, yProto, 0);
			delete strProto;
		}
		~UserSocket()
		{
			if(fd >= 0)
				close(fd);
			if(th_read != 0)
				pthread_join(th_read, NULL);
			if(th_listen != 0)
				pthread_join(th_listen, NULL);
		}
		bool isGood_to_use()
		{
			if(fd < 0) return false;
			return true;
		}
		bool bind_in(const unsigned short xPort)
		{
			if(!isGood_to_use()) return false;
 
			memset(&local_addr, 0, sizeof(local_addr));
			local_addr.sin_family = AF_INET;
			local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
			local_addr.sin_port = htons(xPort);
 
			if(bind(fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0)
				return false;
			return true;
		}
		bool bind_in(const char *xAddr, const unsigned short xPort)
		{
			if(!isGood_to_use()) return false;
 
			memset(&local_addr, 0, sizeof(local_addr));
			local_addr.sin_family = AF_INET;
			local_addr.sin_addr.s_addr = inet_addr(xAddr);
			local_addr.sin_port = htons(xPort);
 
			if(bind(fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0)
				return false;
			return true;
		}
		bool listen_in()
		{
 
			if(!isGood_to_use()) return false;
 
			if(listen(fd, 5) < 0) return false;
			return start_listen_thread();
		}
		bool accept_in(const int xFd, const struct sockaddr_in xAddr)
		{
			fd = xFd;
			memcpy(&remote_addr, &xAddr, sizeof(sockaddr_in));
			if(start_receive_thread())
			{
				sendable = true;
				onAccept();
				return true;
			}
			return false;
		}
		bool getSendable()
		{
			return sendable;
		}
		bool sendData(const char *xData, unsigned int xLen)
		{
			if(!getSendable()) return false;
			if(write(fd, xData, xLen) < 0) return false;
			return true;
		}
		void disconnect()
		{
			if(!isGood_to_use()) return;
			close(fd); fd = -1;
			onClose();
		}
};
gilgil의 이미지

class UserSocket
{
	public:
		//Call back events
		//콜백 이벤트
		virtual void onData_receive(const int dataSize, const char *data){}
MyAbby의 이미지

virtual을 달아 봤지만 여전히 오버라이딩이 안됩니다. 원래 virtual 키워드가 없어도 오버라이드 되는게 정상 아닌가요?

아마 쓰레드를 사용해서 객체가 2개가 된게 아닌듯 싶습니다.. 으이; 뭐지

shint의 이미지

이런 결과가 나오네요.
전 그냥 편하게 이런 방식으로 개발합니다. ㅇ_ㅇ;;

//http://no1rogue.blog.me/30096664831

#include <cstdlib>
#include <iostream>
 
#include <process.h>                 //_beginthreadex
 
 
using namespace std;
 
 
unsigned int __stdcall td(void* arg);
 
 
class UserSocket
{
	public:
//friend class CSocket;
       void* pmain;
       void fn_setMain(void* p)
       {
            pmain = p;
       }
		void onConnection_request(const int fd)
        {
             printf("UserSocket - onConnection_request(%d)\n", fd);
        }
 
		UserSocket(const char *xProto)
		{
                printf("UserSocket\n");
		}
		~UserSocket()
		{
                printf("~UserSocket\n");
		}
 
	private:
            unsigned int id;
            //static unsigned int __stdcall td(void* arg);
//		pthread_t th_listen = 0, th_read = 0;
	private:
		static void *listen_thread_func(void *arg)
		{
/*
			class UserSocket us = *(UserSocket*)arg;
			sockaddr_in remote_addr;
			int lst;
			unsigned int SZ_REMOTE_ADDR = sizeof(remote_addr);
			while(true)
			{
				lst = accept(us.getFd(),
						(struct sockaddr*)&remote_addr, &SZ_REMOTE_ADDR);
				if(lst < 0) break;
				us.onConnection_request(lst, remote_addr);
			}
*/
		}
 
    public:
		bool start_listen_thread()
		{
                printf("UserSocket - start_listen_thread PREV\n");
             //argument of type `unsigned int (UserSocket::)(void*)' does not match `unsigned int (*)(void*)' 
             _beginthreadex(NULL, 0, td, pmain, 0, &id);
                printf("UserSocket - start_listen_thread NEXT\n");
//			if(pthread_create(&th_listen, NULL, listen_thread_func, (void*)this) < 0)
//				return false;
			return true;
		}
 
};
 
class CSocket : public UserSocket
{
public:
//       virtual void onConnection_request(const int fd)
       void onConnection_request(const int fd)
       {
                printf("CSocket - onConnection_request(%d)\n", fd);
       }
public:
       CSocket() : UserSocket("tcp")
       {
                printf("CSocket\n");
       }
       ~CSocket()
       {
                printf("~CSocket\n");
       }
       void fn_run()
       {
            fn_setMain(this);
       }
};
 
 
//static unsigned int __stdcall td(void* arg)
unsigned int __stdcall td(void* arg)
{
    printf("UserSocket - td PREV\n");
//       class UserSocket us = *(UserSocket*)arg;
         UserSocket* pus = (UserSocket*)arg;
         if(pus == NULL)
         {
                printf("pus is NULL\n");
                return 0;
         }
    printf("UserSocket - td CENTER\n");
//       us.onConnection_request(10);
         pus->onConnection_request(11);
         ((CSocket*)pus)->onConnection_request(12);
    printf("UserSocket - td NEXT\n");
}
 
 
int main(int argc, char *argv[])
{
    CSocket s;
//    s.onConnection_request(1);
//    ((UserSocket)s).onConnection_request(2);
    s.start_listen_thread();
    ((UserSocket)s).fn_setMain(&s);
    ((UserSocket)s).start_listen_thread();
 
    printf("---------------------------------\n");
//    UserSocket us("test");
//    us.start_listen_thread();
 
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
 
//출력 결과
UserSocket
CSocket
UserSocket - start_listen_thread PREV
UserSocket - start_listen_thread NEXT
~UserSocket
UserSocket - start_listen_thread PREV
UserSocket - start_listen_thread NEXT
~UserSocket
---------------------------------
UserSocket - td PREV
UserSocket - td CENTER
UserSocket - onConnection_request(11)
CSocket - onConnection_request(12)
UserSocket - td NEXT
UserSocket - td PREV
UserSocket - td CENTER
UserSocket - onConnection_request(11)
CSocket - onConnection_request(12)
UserSocket - td NEXT

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

댓글 달기

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