Shinnara's Blog
Talking with Shinnara :: NaraTalk.com

TCP_NODELAY 적용

Computer/Programming/Java 2007/09/13 15:28 by Shinnara
socket 을 이용하여 통신을 하는데, 반응 속도가 느리다면 tcp_nodelay 옵션을 사용해보는 것도 좋은 방법일 수 있습니다.

tcp socket 의 경우, 기본적으로 Nagle 알고리즘을 사용합니다. Nagle 알고리즘은 전송의 효율을 위해, 적은 데이터를 모아서 큰 패킷으로 한번에 보내는 방식입니다. 따라서 이경우 적은 양의 데이터가 자주 발생되는 시스템에서는 반응속도가 느려질 수 있습니다.

이를 해결하기 위해 socket.setTcpNoDelay(true) 를 해주면 Nagle 알고리즘이 해제되면서, 패킷이 준비되면 바로 보내게 됩니다.

setTcpNoDelay

public void setTcpNoDelay(boolean on)
                   throws SocketException
    Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).

Parameters:
    on - true to enable TCP_NODELAY, false to disable.
Throws:
    SocketException - if there is an error in the underlying protocol, such as a TCP error.
Since:
    JDK1.1
See Also:
    getTcpNoDelay()


하지만 TCP_NODELAY 를 사용하게 되면 반응속도가 증가될 수는 있으나, 네트워크의 효율이 감소하고 시스템의 부하가 늘어나게 되니 꼭 필요한 경우에만 사용하시기 바랍니다.

C에서는 다음과 같이 해주시면 됩니다.

nt nValue = 1;

setsockopt( TCP_NODELAY, &nValue, sizeof(int), IPPROTO_TCP );

0 Trackback, 0 Comment

TRACKBACK :: http://naratalk.com/trackback/138 관련글 쓰기

댓글을 달아 주세요


요즘 이기종 플랫폼에서 서비스를 위해 작업을 하다보니 많은 내용들을 새롭게 알게 됩니다. 정말 배우는 즐거움이란...^^

어제 오늘 열심히 파헤친 분야는 바로 Encoding ...  어제는 W3C 사이트에서 많은 자료를 읽고, 오늘은 UTF-8 처리에 대해 Survey 를 하였다. 그러면서 개발 환경을 모두 UTF-8 로 바꾸기 위한 작업도 함께 했다.

제일 먼저 한건 eclipse 에서 기본 encoding 을 UTF-8 로 바꾼 것..
자주 쓰는 텍스트 에디터인 AcroEdit 도 UTF-8 으로 변경
윈도우에서 FreeBSD 에 접속하기 위해 Zterm 을 주로 썼는데, UTF-8 이 안되는 이유로 Putty 로 변경

어서 모든 환경에서 UTF-8 만 쓰였으면 좋겠다는 말도 안되는 생각을 하며...

개발하고 있는 부분에 UTF-8 처리를 구현하는 과정에서 알게 된 팁 한가지.. 어찌보면 정말 당연한 것인데 한참 헤맬뻔 했다.

바로 소켓 통신시 인코딩 문제.. 보통 String 데이터를 보내기 위해 getBytes() 를 하는데, 이때 charset 을 지정하지 않으면 시스템의 기본 설정으로 인코딩 된다는것... 이 좋은 사실을 알려준 사이트는 여기.

위 사이트에 있는 것처럼 코드를 작성하여 돌려보았다.

public class EncodingTest {
    public static void main(String[] args)
    {
        System.out.println("file.encoding=" + System.getProperty("file.encoding"));
    }
}


내 FreeBSD 6.2 에서 돌려본 결과

file.encoding=ISO8859-1


윈도우 XP 에서 돌려본 결과는

file.encoding=MS949


Linux 에서 돌려보니

file.encoding=EUC-KR


이렇게 나오는것이다. 만약 이 세 머신들이 각각 소켓통신을 하면서 아스키 이외의 문자를 주고 받는다면 그 결과는 뻔한것 아닌가...

소켓 프로그래밍을 하는 데 있어 꼭 필요한 팁이 아닌가 싶다.


update : 글을 올리고 위의 블로그를 보다보니 좋은 내용이 있어서 공유합니다.

javascript 의 escape 함수를 java로 구현

public static String escape(String string){
       StringBuffer sb = new StringBuffer();
       String ncStr = "*+-./0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
       char c;
      
       for(int i=0;i<string.length();i++){
              c = string.charAt(i);
              if(c>0x7f)
                     sb.append("%u" + Integer.toHexString((int)c).toUpperCase());
              else if(ncStr.indexOf((int)c)==-1){
                     sb.append('%');
                     if(c<=0xf)
                            sb.append('0');
                     sb.append(Integer.toHexString((int)c).toUpperCase());
              }
              else
                     sb.append(c);
       }
      
       return sb.toString();
}

0 Trackback, 0 Comment

TRACKBACK :: http://naratalk.com/trackback/124 관련글 쓰기

댓글을 달아 주세요

검색을 하다 유용한 내용이 있어서 옮겨봅니다.

원문 출처는 다음과 같습니다.

Java에서 C 모듈과의 소켓통신시 유의사항
http://cafe.naver.com/nwcomcokr/897 


잘 알다시피 자바는 JVM 플랫폼 위에서 연동되며 소켓통신등의 바이트 전송시 byte order 가 BIG_ENDIAN 이다. 하지만 C 처럼 실행파일이 만들어지는 경우는 해당 플랫폼에 따라서(좀 더 정확히는 CPU 종류에 따라서) byte order 가 달라진다.

intel, alpha 와 같은 경우에는 LITTLE_ENDIAN이며, sun sparc, mac os, 그리고 JVM 같은 경우에는 BIG_ENDIAN 이다.

c 의 경우 플랫폼별로 1 바이트를 이루는 크기가 다른데 이는 보통 /usr/include/machine 의 limits.h 와 같은 곳에 CHAR_BIT 이라는 이름으로 정의되어 있으며 byte order 는 /usr/include/macine 에 endian.h 와 같은 형태로 되어 있다.
다음은 intel 용 freebsd 의 endian.h 의 내용중 일부이다.


#define LITTLE_ENDIAN   1234    /* LSB first: i386, vax */
#define BIG_ENDIAN      4321    /* MSB first: 68000, ibm, net */
#define PDP_ENDIAN      3412    /* LSB first in word, MSW first in long */

#define BYTE_ORDER      LITTLE_ENDIAN


16bit OS 의 경우 한번에 2바이트씩 전송한다고 볼 수 있으므로(안그런 경우도 있지만) 만약 32bit 의 자료형을 전송하게 되면 이를 16bit 찍 잘라서 전송하게 되는데, 이때부터 byte order 의 문제가 발생한다.

전송해야 하는 4 byte 가 1 2 3 4 와 같이 있다고 할때, big_endian 은 12   34  이렇게 전송을 하고, little_endian 은 34   12  이렇게 나눠서 전송을 한다고 생각하면 쉬울 것이다.

따라서 전송하는 쪽의 내용과 받는쪽의 내용이 4 byte를 기준으로 상위 2byte 와 하위 2byte가 서로 상이하게 될 수가 있다.

이는 굳이 자바와 C 사이의 소켓통신뿐만이 아니라 이기종간 C와 C사이 통신에서는 언제든지 발생할 수 있는 상황이다.


해결책은?

별다른건 없다. 자바쪽에서는 보낼때 BIG_ENDIAN 으로 전송하고, 상대방쪽이 자바모듈이 아닐 경우는 플랫폼 정보를 얻은 다음 전송되어 온 바이트를 적절히 바꿔주면 된다.

C 의 경우는 endian.h 의 정보에 따라서 코딩을 해주면 된다.

if (  BYTE_ORDER == BIG_ENDIAN )
   // 1234 로 전송해
else if ( BYTE_ORDER == LITTLE_ENDIAN )
  // 4321 로 전송해

이런식으로 하면 소스수준의 이식성을 높일 수가 있을 뿐만 아니라 다른 시스템과의 소켓통신 등에도 유용하게 사용할 수 있다.
이런때 써먹기 위한 함수가 몇개 있는데(물론 c에서..) htonl, htons, ntohl, ntohs 등이 그것이다.
각각의 사용법은 알아서 발견하는 기쁨을 누려보도록 하자.

0 Trackback, 0 Comment

TRACKBACK :: http://naratalk.com/trackback/113 관련글 쓰기

댓글을 달아 주세요

1 
다...... (264)
Computer/Programming (106)
Links (14)
책 읽는 즐거움 (7)
끄적임 (66)
즐거운 과학 나라 (7)
일본 (5)
Study (4)