JSP에서 클라이언트의 IP 주소를 확인하기 위해 다음과 같이 할 수 있다.

<%
out.print("<p>Remote Addr: " + request.getRemoteAddr() + "</p>");
out.print("<p>Remote Host: " + request.getRemoteHost() + "</p>");
out.print("<p>X-Forwarded-For: " + request.getHeader("x-forwarded-for") + "</p>");
%>

getRemoteAddr()이나 getRemoteHost()나 같은 값을 돌려준다.

x-forwarded-for는 클라이언트가 프록시 (Proxy) 뒤에 있을 경우 실제 IP 주소를 알기 위한 용도로 사용할 수 있다.

다음은 이를 테스트하는 페이지이다.

http://cushion.flxsrv.biz/services/identify_ip.jsp

자신의 Public IP 주소를 확인하고자 할 때 유용하겠다.


출처 - http://devday.tistory.com/entry/JSP%EC%97%90%EC%84%9C-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-Client-IP-%EC%A3%BC%EC%86%8C-Address-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0


==================================================================================


이번 개발에 있어서 윈도우 이클립스에서 개발한 서버가 리눅스 환경에서 일부 기능에 문제가 있어서 찾다보니 같은 메소드지만 윈도우 환경에서 로컬 ip주소를 얻어오는 코드가 리눅스에서는 "127.0.0.1"을 가져와서 문제가 되었다. 구글에서 검색한 결과 코드가 좀 길고 지저분하지만 아래 코드를 써줘야 했다.

* Windows
 try {

System.out.println(InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}

 

* Linux
try {
String ip = null;

boolean isLoopBack = true;
Enumeration<NetworkInterface> en;
en = NetworkInterface.getNetworkInterfaces();

while(en.hasMoreElements()) {
NetworkInterface ni = en.nextElement();
if (ni.isLoopback())
continue;

Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
while(inetAddresses.hasMoreElements()) { 
InetAddress ia = inetAddresses.nextElement();
if (ia.getHostAddress() != null && ia.getHostAddress().indexOf(".") != -1) {
ip = ia.getHostAddress();
System.out.println(ip);
isLoopBack = false;
break;
}
}
if (!isLoopBack)
break;
}
System.out.println(" IP  =   " + ip);
} catch (SocketException e) {
e.printStackTrace();
}


출처 - http://atin.tistory.com/341


===================================================================================


import java.net.*;

 

 

InetAddress Address = InetAddress.getLocalHost();


System.out.println("로컬 컴퓨터의 이름 : "+Address.getHostName());


System.out.println("로컬 컴퓨터의 IP 주소 : "+Address.getHostAddress());


Address = InetAddress.getByName("java.sun.com");


System.out.println("java.sun.com 컴퓨터의 이름과 IP 주소 : "+Address);


InetAddress SW[] = InetAddress.getAllByName("www.hollywood.com");


for (int i=0; i System.out.println(SW[i]);


출처 - http://blog.naver.com/PostView.nhn?blogId=aegisfight&logNo=100030866626


===================================================================================


Java에서 Localhost의 IP를 확인방법은 java.net package의 InetAddress 클래스를 이용하는
것이 일반적이다. 그러나 Window와는 달리 UNIX/LINUX에서는 문제가 발생할 소지가 있다.
InetAddress 는 기본적으로 Hostname로 IP Address를 가지고 오는 방법을 취하고 있는데
UNIX의 경우는 내부적으로 SecurityManager.checkConnect()의 호출에서 Exception발생시
Loopback Address를 리턴하게 되어 실제 Localhost의 IP를 얻어오지 못하는 경우가 발생한다.

이런 문제 때문에 java 1.4에서 새로 생긴 java.net package의 NetworkInterface 클래스를 이용하여
IP를 가지고 오는 방법을 취한다.
그러나 또다른 문제가 발생된다. NetworkInterface은 Ethernet 장치기반으로 IP를 Enumeration으로
반환하기 때문에 여러개의 Ethernet 장치가 존재할 경우에는 원하는 IP를 선택하여야 할 상황이
생기게 된다.

자! 그래서 소스
public static void main(String args[]) throws SocketException{
Enumeration<NetworkInterface> nienum = NetworkInterface.getNetworkInterfaces();
        while (nienum.hasMoreElements()) {
            NetworkInterface ni = nienum.nextElement();
            Enumeration<InetAddress> kk = ni.getInetAddresses();
            
            while (kk.hasMoreElements()) {
     InetAddress inetAddress = (InetAddress) kk.nextElement();
     System.out.println(inetAddress.getHostName()+" : "+inetAddress.getHostAddress());
     }
        }
        
}


출처 - http://suein1209.tistory.com/568




Posted by linuxism
,


DISTINCT 와 GROUP BY의 차이

DISTINCT는 주로 UNIQUE한 컬럼이나 튜플(레코드)을 조회하는 경우 사용되며,
GROUP BY는 데이터를 그룹핑해서 그 결과를 가져오는 경우 사용되는 쿼리 형태이다.


하지만 두 작업은 조금만 생각해보면 동일한 형태의 작업이라는 것을 쉽게 알 수 있으며,
일부 작업의 경우 DISTINCT로 동시에 GROUP BY로도 처리될 수 있는 쿼리들이 있다.
그래서 DISTINCT를 사용해야 할지, GROUP BY를 사용해서 데이터를 조회하는 것이 
좋을지 고민되는 경우들이 가끔 있다.


간단하게 아래 예를 살펴 보자
1. SELECT DISTINCT fd1 FROM tab;
2. SELECT DISTINCT fd1, fd2 FROM tab;


위의 두개 쿼리는 간단히 GROUP BY로 바꿔서 실행할 수 있다.
1. SELECT fd1 FROM tab GROUP BY fd1;
2. SELECT fd1, fd2 FROM tab GROUP BY fd1, fd2;


그렇다면 이 예제의 쿼리에서 DISTINCT와 GROUP BY 는 어떤 부분이 다를까 ?
사실 이런 형태의 DISTINCT는 내부적으로 GROUP BY와 동일한 코드를 사용한다.
즉, 동일한 처리를 하게 된다는 것이다. 


하지만 더 중요한 차이가 있다.
DISTINCT의 결과를 정렬된 결과가 아니지만, GROUP BY는 정렬된 결과를 보내준다.
GROUP BY의 작업을 크게 "그룹핑" + "정렬"로 나누어서 본다면, DISTINCT는 "그룹핑" 작업만
수행하고 "정렬" 작업은 수행하지 않는 것이다.
그런데, 여기서 "정렬"은 "그룹핑" 과정의 산물이 아닌 부가적인 작업이다.


최종적으로, 이 예제의 DISTINCT와 GROUP BY는 일부 작업은 동일하지만 GROUP BY는
"정렬"을 하기 위한 부가적인 작업을 더 하게 된다.


만약 "정렬"이 필요하지 않다면 DISTINCT를 사용하는 것이 성능상 더 빠르다고 볼 수 있다.
하지만, GROUP BY를 사용하는 경우에는 정렬을 하지 않도록 유도할 수 있다.
(자세한 내용은 "GROUP BY의 Filesort 작업 제거"를 참조)




참고로
GROUP BY와 DISTINCT는 각자 고유의 기능이 있다.


DISTINCT로만 가능한 기능
1. SELECT COUNT(DISTINCT fd1) FROM tab;
    -- // 이런 형태의 쿼리는 서브 쿼리를 사용하지 않으면 GROUP BY로는 작성하기 어렵다.


GROUP BY로만 가능한 기능
1. SELECT fd1, MIN(fd2), MAX(fd2) FROM tab GROUP BY fd1;
    -- // 이렇게 집합함수(Aggregation)가 필요한 경우에는 GROUP BY를 사용해야 한다.




<<주의사항>>
가끔 어떤 사용자는 DISTINCT가 마치 함수인 것처럼 (괄호를 사용하여) 아래와 같이 사용을 하는데
만약 fd1 컬럼은 unique 값, fd2는 전체 값을 원한다면 절대 그 결과를 얻을 수 없다.


SELECT DISTINCT(fd1), fd2 FROM tab;

SELECT 문장에 DISTINCT라는 키워드가 있으면, MySQL은 SELECT되는 모든 컬럼(튜플)들에 대해서 DISTINCT를 적용해서 결과를 보내주게 된다.
위와 같은 요건을 처리하기 위해서도 아래와 같이 GROUP BY로만 해결할 수 있다.

SELECT fd1, fd2 FROM tab GROUP BY fd1;


출처 - http://intomysql.blogspot.kr/2011/01/distinct-group-by.html



Posted by linuxism
,

mysql - union 연산자

DB/MySQL 2012. 8. 20. 14:57



MySQL 등의 RDBMS에서 사용하는 Union 연산자는 여러 테이블에 존재는 같은 성격의 값을 한번의 쿼리로 추출할 수 있도록 돕는다.

예를 들어 Member 테이블에 회원 이메일이 있고, Newsletter 테이블에 구독자 이메일이 있는데, 모든 이메일로 메일을 보내고자 할 경우 두번의 쿼리와 병합 프로그램을 만들어야 할 것이다. 이럴 때 union 연산자를 사용하면 한번의 쿼리로 간단하게 정보를 추출할 수 있다.

Union을 사용할 때 주의할 점.
- 대응하는 필드의 이름이 같아야 한다. 같지 않다면 AS 를 사용하여 같게 만든다.
- 대응되는 각 필드의 타입이 같아야 한다.



* Member 테이블
 seq u_name u_email  etc 
 1 개똥이 aa@aa.co.kr ...
 2 소똥이 bb@bb.co.kr ...
 3 말똥이 cc@cc.co.kr ...

* Newsletter 테이블
letter_ seq letter_name letter_email  letter_etc 
 1 홍길동 aa@aa.co.kr ...
 2 홍당무 dd@d.co.kr ...
 3 노찌롱 ee@ee.co.kr ...

위의 2개 테이블에서 이메일을 추출해야 할 경우 union을 사용하면 간단하다. 

이렇게 추출할 경우 중복되지 않은 유일한 정보 만을 추출하는 경우와 중복되더라도 모두 추출하는 경우가 있을 것이다.


Union 을 사용하는 경우 대응되는 각 필드의 이름을 같게 맞추어 쿼리를 한다.
( SELECT u_name, u_email FROM Member WHERE seq < 10 )
UNION
( SELECT letter_name AS u_name, letter_email AS u_email FROM Newsletter WHERE letter_seq < 10 )


이렇게 쿼리를 하면 이름(user_name)과 이메일(user_email)이 같은 경우 하나의 값 만 추출하여 distinct 함수와 같은 효과를 준다.


만약 중복되더라도 모든 정보를 추출해야 한다면 Union ALL 연산자를 이용하면 된다.
( SELECT u_name, u_email FROM Member WHERE seq < 10 )
UNION ALL
( SELECT letter_name AS u_name, letter_email AS u_email FROM Newsletter WHERE letter_seq < 10 )


UNION ALL 연산자를 이용하면 간단하게 처리가 가능하다.


UNION을 하면 결과가 테이블에 종속되는 것이 아니다. 그러므로 결과를 정렬을 해야 한다면 쿼리의 끝에 정렬을 추가하면 된다.
( SELECT u_name, u_email FROM Member WHERE seq < 10 )
UNION
( SELECT letter_name AS u_name, letter_email AS u_email FROM Newsletter WHERE letter_seq < 10 )
ORDER BY u_email


출처 - http://blog.bsmind.co.kr/377




Posted by linuxism
,