[질문]/dev/poll 이용한 소켓 프로그램 질문입니다.

paraline의 이미지

안녕하세요?
솔라리스에서 서버 프로그래밍 중입니다.
예전에는 select를 이용해서 프로그래밍을 했었는데, 솔라리스에 /dev/poll이라는 것이 있다는 얘기를 접하고, /dev/poll을 이용해서 서버를 구축하려 합니다.
샘플 소스를 찾아봐도 검색실력이 딸려서 인지, UDP 쪽 소스는 구했는데, TCP는 못하겠군요.
제가 궁금한건 샘플 소스를 보면서 여쭙겠습니다.

while(1)
{
	close(wfd); 
	if ((wfd = open("/dev/poll", O_RDWR)) < 0) { 
		perror("cannot open /dev/poll"); 
		exit(-1); 
	} 
	
	// 첫번째 질문
	if (write(wfd, &fds[0], 
		sizeof(struct pollfd) * MAXSOCKS) != 
		sizeof(struct pollfd) * MAXSOCKS) { 
		perror("failed to write all pollfds"); 
		close (wfd); 
		exit(-1); 
	} 

	result = ioctl(wfd, DP_POLL, &dopoll); 
	
	if (result < 0) { 
		perror("/dev/poll ioctl DP_POLL failed"); 
		close (wfd); 
		exit(-1); 
	} 
	
	for (int i = 0; i < result; i++)
	{ 
		tfd = dopoll.dp_fds[i].fd; 
		if(dopoll.dp_fds[i].revents & POLLIN)
		{ 
			if(tfd == fds[0].fd)
			{
				nAddrLen = sizeof(ClientAddr);
				if((nClientFd = accept(fds[0].fd, (struct sockaddr *)&ClientAddr, &nAddrLen)) < 0)
				{
					perror("accept");
					continue;
				}
				else
				{
					// 두번째 질문
				}
			}
			else
			{
				int nRead = 0;		
				memset(szBuffer, 0x00, sizeof(szBuffer));
				if ((nRead = recv(tfd, szBuffer, sizeof(szBuffer), 0))== -1){ 
					
					if (errno == EWOULDBLOCK) { 
						perror("EWOULDBLOCK");
						break; 
					} 
					else { 
						// ...
					} 
				} 
				else if(nRead == 0)
				{
					// ...
				}
				else
				{
					// ...
				}
			}
		} 
	} // for(i = 1; i < result; i ++)
} // while(1)

위와 같은 코드에서 struct pollfd fds[MAXSOCKS]를 선언하고,
fds[0].fd를 리슨 소켓으로 할당했습니다.
처음에는 // 첫번째 질문의 write(...)가 어떤 역할을 하는지 몰라서, 주석처리했더니, 아예 동작을 안하더군요. 그래서, write(...)를 추가했는데, 왜 매번 close(wfd)를 호출하고, 다시 open을 하는지 잘 모르겠습니다.
그리고, // 두번째 질문에서, accept 후에 리턴되는 fd를 어떻게 등록해야 하는지도 잘 모르겠습니다.
매번 fds[MAXSOCKS] 중에서 할당되어 있지 않은 곳을 찾아서, accept 된 fd를 넣어 주는것인지, 아니면, 어떻게 하는것인지요?
검색을 해보니, 관심 fd를 write에서 등록한다고 한다는 말이 있던데, 구체적으로 어떻게 하는건지 가르쳐 주시면 감사하겠습니다.
그리고, 혹시 /dev/poll을 이용한 간단한 TCP 서버 샘플이 있으시면 좀 가르쳐 주십시오.

답변 주실 모든 분들께 미리 감사의 말씀을 전합니다.

bugiii의 이미지

여러가지 이벤트 검출 기능을 감싸주는

http://monkey.org/~provos/libevent/

를 한번 살펴보시는 것도 좋겠습니다.

paraline의 이미지

bugiii wrote:
여러가지 이벤트 검출 기능을 감싸주는

http://monkey.org/~provos/libevent/

를 한번 살펴보시는 것도 좋겠습니다.


가르쳐주신 내용은 저도 봤던것인데, 소스에 있는 내용을 소켓에 적용하기가 좀 난해하더군요. 좀 더 시간을 갖고 분석해야 할것 같습니다.
좋은 내용을 가르쳐주셨는데, 제가 허접이라 제대로 활용을 못하고 있네요.

지금 당장 궁금한것은 // 두번째 질문에 해당하는 관심 fd를 어떻게 등록을 하는지 입니다. write(...)로 관심 fd를 등록하는것 같은데, 어떻게 해야할지 감이 안잡히는군요.

힌트를 좀 주셨으면 합니다.

좌절금지!!!
피할수 없다면 즐겨라.

익명 사용자의 이미지

paraline wrote:
#define MAXSOCKS 256 // 30000
	// 첫번째 질문
	if (write(wfd, &fds[0], 
		sizeof(struct pollfd) * MAXSOCKS) != 
		sizeof(struct pollfd) * MAXSOCKS) { 
		perror("failed to write all pollfds"); 
		close (wfd); 
		exit(-1); 
	} 

	...	
	
	for (int i = 0; i < result; i++)
	{ 
		tfd = dopoll.dp_fds[i].fd; 
	} // for(i = 1; i < result; i ++)

1. MAXSOCKS이 30000일때, write 에러가 나서, ulimit -a 해서 보니까, open files가 256이었습니다. 그래서, ulimit -n으로 30000으로 바꿨더니, write에서 에러가 발생하지 않았습니다.
이 부분이 이해가 안되는데요. select는 FD_SETSIZE가 1024로 제한이 있고, poll은 제한이 없다고 들었는데, /dev/poll도 제한이 없는것 아닌가요?
그런데, 왜 open files 보다 큰 수일때, 에러가 나는지 모르겠습니다.
FD_SETSIZE는 file descriptor의 수와는 상관없이, 단순히 select할때, 체크할수 있는 수를 의미하는 건가요? 그렇다면 FD_SETSIZE의 제한이 open files의 제한을 의미하는것은 아니라고 이해해도 될까요?

2. 위에서 i가 3일 경우, dopoll.dp_fds[3].fd과 fds[3].fd의 값이 서로 다른데, fds[i]와 dopoll.dp_fds[i]는 서로 다른 값인가요?
그렇다면, dopoll.dp_fds[i].fd에 해당하는 fds[i].fd를 어떻게 찾아야 하는지요?
이걸 찾아야 해당 fds[i].events에 POLLIN과 같은 값을 등록할수 있을것 같은데 말입니다.

질문이 좀 두서없습니다만, 관심가져주시고, 답변도 부탁드립니다.

익명 사용자의 이미지

안녕하세요?
질문은 자꾸 늘어가는데, 답변은...
아무래도 노력하지 않고, 답만 달라고 해서 밉게 보시는게 아닐런지...

이번 질문은 다음과 같습니다.
특정 fd에 대해서, 읽기가 가능한지를 체크할때, event에 POLLIN을, 쓰기가 가능한지를 체크할때, POLLOUT을, 체크하고 싶지 않을때, POLLREMOVE를 사용하는걸로 이해하고 있습니다. 여기까지는 맞는지요?

클라이언트가 연결되었을때, POLLIN을 설정하고 나서, 클라이언트가 메세지를 보냈을때, 서버에서 메세지를 받은 후에, events |= POLLOUT 이런식으로 설정을 해주고, 쓰기 가능할때, 답을 보내는 식으로 하고 있습니다.

그런데, 제가 원하는것은 일단 답을 보낸다음에는 POLLOUT을 체크하지 않기 위해서, POLLOUT event를 제거하고 싶은데, events = POLLIN으로 다시 해주거나, events &= ~POLLOUT으로 해봐도 POLLOUT이 제거가 안되고 여전히 남아있습니다. 왜 그런지 이유를 모르겠습니다. events = POLLREMOVE 로 해보면 POLLIN이나 POLLOUT 모두 정상적으로 제거가 되는데, 왜 POLLOUT만 제거하려면 안되는걸까요? 어디가 틀렸는지 도저히 모르겠네요.

조언 부탁드립니다.

댓글 달기

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