태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

eternally full with hope...

블로그 이미지
영원히 희망으로 가득하길...
by eternalbleu
  • 464617Total hit
  • 100Today hit
  • 316Yesterday hit

'CS&E/Network'에 해당되는 글 8건

  1. 2008/01/07
    도메인 기관 이전 이라는 것을 처음으로 해봤습니다.
  2. 2006/08/12
    ACE(Adaptive Communication Environment) 써본 소감... (2)
  3. 2006/07/15
    Distance Vector vs. Link-State
  4. 2006/07/08
    Adhoc Network & Sensor Network
  5. 2006/05/22
    분산처리 ㅡ.ㅡ
  6. 2006/05/15
    Gnutella(Gnucleus) 프로토콜 해설
  7. 2006/04/05
    웹 프락시 작성
  8. 2006/03/27
    다중 연결 허용 서버의 구현법 (socket programming)

도메인 신청에 대해서 아무것도 모르던 때에 현재 도메인을 구입해서 상대적으로 가격이 엄청 비쌌던 후이즈에서 신청을 했었습니다. (후이즈는 왜 이렇게 비쌀까요?)

전 원래 그 가격에만 등록이 돼는 줄 알았는데... 쩝...

하여간 슬슬 기간도 반년정도만 남아서 dotname으로 등록 기관을 이전했습니다.

생각보다 엄청 간단하더군요. ;;

그냥 기존의 등록기관에서 AUTH CODE를 받아서 새로운 등록 기관으로 신청만 하면 돼더라는...

사용자 삽입 이미지

TRACKBACK 0 AND COMMENT 0
멤에서 이번에 소규모 1주일 텀프로젝트를 시작하면서 절대로 이유없이 프로그램 만들지 않는 내가 ACE를 공부해자는 마음으로 이 놈을 공부를 했다.

단순히 통신을 이루는 행위 자체는 굉장히 간단했다.

ACE 프레임워크 스택



문제는 이런 것이 아니라... 도대체 내가 만드는 코드가 밑에서 어떻게 돌아가는지 알 수가 없었다. MFC 도 아닌 녀석이 MFC 흉내를 내는 건지;;;

확실히 소켓처럼 저순으로 돌아가는 내용을 몰라도 프로그램을 잘 작성된다. 하지만 그것뿐이다. 절대로 처음 네트워크를 프로그래밍하는 사람에게는 비추인 녀석이다. 덴장;;;

프레임웍은 DP를 공부하는 목적으로 대단히 적합하다. 그만큼 방대하기 이를데 없고.... 이런것까지 ACE에서 지원해야하나 싶을 정도로 엄청나다.
TRACKBACK 0 AND COMMENT 2
Distance Vector Routing Protocol
A distance-vector routing protocol is a routing protocol used in routing of packet-switched networks in computer communications, as in for example the Routing Information Protocol for Internet traffic. They use the Bellman-Ford algorithm to calculate paths.

Examples of distance-vector routing protocols include RIPv1 or 2 and IGRP.

Working
The distance-vector routing protocol assumes a network connected through several
routers, each of which is connected to two or more computer networks. Each network may be connected to one or more routers.

The description below describes a very simple distance-vector routing protocol:

  1. In the first stages, the router makes a list of which networks it can reach, and the cost to reach them (cost is protocol dependent, in RIP case, the cost is measured by number hops). In the outset this will be the two or more networks to which this router is connected. The number of hops for these networks will be 1. This table is called a routing table.
  2. Periodically (typically every 30 seconds) the routing table is shared with other routers on each of the connected networks via some specified inter-router protocol. These routers will add 1 to every hop-count in the table, as it associates a hop cost of 1 for reaching the router that sent the table. This information is just shared inbetween physically connected routers ("neighbors"), so routers on other networks are not reached by the new routing tables yet.
  3. A new routing table is constructed based on the directly configured network interfaces, as before, with the addition of the new information received from other routers. The hop-count is used as a cost measure for each path. The table also contains a column stating which router offered this hop count, so that the router knows who is next in line for reaching a certain network.
  4. Bad routing paths are then purged from the new routing table. If two identical paths to the same network exist, only the one with the smallest hop-count is kept. When the new table has been cleaned up, it may be used to replace the existing routing table used for packet forwarding.
  5. The new routing table is then communicated to all neighbors of this router. This way the routing information will spread and eventually all routers know the routing path to each network, which router it shall use to reach this network, and to which router it shall route next.

Advantage and Disadvantage
Distance-vector routing protocols are simple and efficient in small networks, and require little, if any management. However, they do not
scale well, and have poor convergence properties, which has led to the development of more complex but more scalable link-state routing protocols for use in large networks. They suffer from the "Count to Infinity problem".


Link State Routing Protocol
A link-state routing protocol is one of the two main classes of routing protocols used in packet-switched networks for computer communications. Examples of link-state routing protocols include OSPF and IS-IS.

The link-state protocol is performed by every switching node in the network (i.e. nodes which are prepared to forward packets; in the Internet, these are called routers). The basic concept of link-state routing is that every node receives a map of the connectivity of the network, in the form of a graph showing which nodes are connected to which other nodes.

Each node then independently calculates the best next hop from it for every possible destination in the network. (It does this using only its local copy of the map, and without communicating in any other way with any other node.) The collection of best next hops forms the routing table for the node.

This contrasts with distance-vector routing protocols, which work by having each node share its routing table with its neighbors. In a link-state protocol, the only information passed between the nodes is information used to construct the connectivity maps.

Detailed Description : Distributing maps
This description covers only the simplest configuration; i.e. one with no areas, so that all nodes do have a map of the entire network. The hierarchical case is somewhat more complex; see the various protocol specifications.

As previously mentioned, the first main stage in the link-state algorithm is to give a map of the network to every node. This is done with several simple subsidiary steps.

Determining the neighbours of each node
First, each node needs to determine what other nodes it is connected to, over fully-working links; it does this using a simple reachability protocol which it runs separately with each of its directly-connected neighbours.

Distributing the information for the map
Next, each node periodically makes up a short message, the link-state advertisement, which:

Identifies the node which is producing it.
Identifies all the other nodes to which it is directly connected.
Includes a sequence number, which increases every time the source node makes up a new version of the message.
This message is then flooded throughout the network. As a necessary precursor, each node in the network remembers, for every other node in the network, the sequence number of the last link-state message which it received from that node. With that in hand, the method used is simple.

Starting with the node which originally produced the message, it sends a copy to all of its neighbours. When a link-state advertisement is received at a node, the node looks up the sequence number it has stored for the source of that link-state message. If this message is newer (i.e. has a higher sequence number), it is saved, and a copy is sent in turn to each of that node's neighbours.

This procedure rapidly gets a copy of the latest version of each node's link-state advertisement to every node in the network.

Creating the map
Finally, with the complete set of link-state advertisements (one from each node in the network) in hand, it is obviously easy to produce the graph for the map of the network.

The algorithm simply iterates over the collection of link-state advertisements; for each one, it makes links on the map of the network, from the node which sent that message, to all the nodes which that message indicates are neighbours of the sending node.

No link is considered to have been correctly reported unless the two ends agree; i.e. if one node reports that it is connected to another, but the other node does not report that it is connected to the first, there is a problem, and the link is not included on the map.

Notes about this stage
The link-state message giving information about the neighbours is recomputed, and then flooded throughout the network, whenever there is a change in the connectivity between the node and its neighbours, e.g. when a link fails. Any such change will be detected by the reachability protocol which each node runs with its neighbours.

Detailed description: Calculating the routing table
As initially mentioned, the second main stage in the link-state algorithm is to produce routing tables, by inspecting the maps. This is again done with several steps.

Calculating the shortest paths
Each node independently runs an algorithm over the map to determine the shortest path from themselves to every other node in the network; generally some variant of Dijkstra's algorithm is used.

Basically, a node maintains two data structures: a tree containing nodes which are "done", and a list of candidates. The algorithm starts with both structures empty; it then adds to the first one the node itself. The algorithm then repetitively:

Adds to the second (candidate) list all nodes which are connected to the node just added to the tree (excepting of course any nodes which are already in either the tree or the candidate list).
Of the nodes in the candidate list, moves to the tree (attaching it to the appropriate neighbour node already there) the one which is the closest to any of the nodes already in the tree.
Repeat as long as there are any nodes left in the candidate list. (When there are none, all the nodes in the network will have been added to the tree.)
This procedure ends with the tree containing all the nodes in the network, with the node on which the algorithm is running as the root of the tree. The shortest path from that node to any other node is indicated by the list of nodes one traverses to get from the root of the tree, to the desired node in the tree.

Filling the routing table
With the shortest paths in hand, filling in the routing table is again obviously easy.

For any given destination node, the best next hop for that destination is the node which is the first step from the root node, down the branch in the shortest-path tree which leads toward the desired destination node.

To create the routing table, it is only necessary to walk the tree, remembering the identity of the node at the head of each branch, and filling in the routing table entry for each node one comes across with that identity.

Optimizations to the algorithm
The algorithm described above was made as simple as possible, to aid in ease of understanding. In practise, there are a number of optimizations which are used.

Most importantly, whenever a change in the connectivity map happens, it is necessary to recompute the shortest-path tree, and then recreate the routing table. The BBN work discovered how to recompute only that part of the tree which could have been affected by a given change in the map.

Also, the routing table would normally be filled in as the shortest-path tree is computed, instead of making it a separate operation.

TRACKBACK 0 AND COMMENT 0

Adhoc Network

In computer networking, ad-hoc is a network connection method which is most often associated with wireless devices. The connection is established for the duration of one session and requires no base station. Instead, devices discover others within range to form a network for those computers. Devices may search for target nodes that are out of range by flooding the network with broadcasts that are forwarded by each node. Connections are possible over multiple nodes (multihop ad-hoc network). Routing protocols then provide stable connections even if nodes are moving around. Both Nintendo's DS and Sony's PlayStation Portable use Ad-Hoc connections for wireless multiplayer gaming.

See IEEE 802.11, Bluetooth, or ultra-wide band. The alternative is infrastructure, with a base station that manages the network for its range.

The term ad-hoc network can also refer to an independent basic service set (IBSS).


Sensor network

A sensor network is a computer network of many, spatially distributed devices using sensors to monitor conditions at different locations, such as temperature, sound, vibration, pressure, motion or pollutants. Usually these devices are small and inexpensive, so that they can be produced and deployed in large numbers, and so their resources in terms of energy, memory, computational speed and bandwidth are severely constrained. Each device is equipped with a radio transceiver, a small microcontroller, and an energy source, usually a battery. The devices use each other to transport data to a monitoring computer.

Sensor networks involve three areas: sensing, communications, and computation (hardware, software, algorithms). Very useful technologies are wireless database technology such as queries, used in a wireless sensor network, and network technology to communicate with other sensors, especially multihop routing protocols. For example, ZigBee is a wireless protocol used by Motorola in home control systems.

TRACKBACK 0 AND COMMENT 0

요즘 준비중인 프로그램이 있습니다. 이녀석이 약간은 분산처리와 비슷한 냄새를 풍기는 놈인데... 이녀석을 다루면서 요즘 참 네트워크를 잘 짜기도 힘들겠구나 싶습니다.

제가 말하는 녀석은 C/S모델이 아닌 말그대로 분산형 처리. Self Routing, Self Recovery 모델을 지원하는 네트워크를 구성하는 녀석들을 말합니다. 이 녀석들을 보면 이 프로로콜을 고안하고 구현한 사람들이 결코 평범한 두뇌를 자랑하는 사람이 아니라는 생각이 듭니다. 각자가 C/S 모두인 이 녀석들은 조금만 컨트롤을 잘못해도 네트웍 전체가 엉켜버리는 군요.

아 답답해... ㅡ.ㅡ;; 그래도 결국엔 네트워크를 붙이는 일을 성공했습니다. 이제 제가 구현하려고 한 프로그램의 대충 50% 정도가 완성된 것 같습니다. 아직도 멀었네요. 한 한달은 빡시게 굴러야 완성되지 않을까 싶습니다. ㅜ.ㅜ

TRACKBACK 0 AND COMMENT 0
파일 공유 프로토콜인 Gnutella 에 대한 분석글
----
= Gnutella-More Free =

== 시작에 앞서서 ==
늦게 이 글을 올린 것에 대해 미안하다.
이 문서는 내가 아르바이트를 하면서 번역과 작성한 문서이다.
지금의 스펙에서는 라우팅 부분의 맴과 캐쉬와 쉐어에서 많은 부분 수정이 가해졌다.
대부분의 P2P 프로그램들이 누텔라의 방법을 기본으로 작성 되었으며 지금의 유동적
IP를 갖는 환경에서는 이를 뛰어 넘는 방법은 없을 것으로 보여진다.
후에 IPv6가 나온다면 각각의 시스템이 아닌 어플리케이션에 IP를 붙일 수 있게 되어진다고
읽은 적이 있다. 이 때 되면 보다 획기적인 P2P 프로그램이 나올 것으로 보인다.

아래의 글은 가볍게 읽어 주시길....

== 주인장이 생각하는 가장 이상적인 P2P란 ==
그누텔라는 확실히 매력적이고 또한 이상적인 순수 P2P라는 생각이 든다. 하지만 P2P란 많은 부분
희생(?)이 필요하다. 여기서 희생이란 불필요하지만 쓸 수 밖이 없는 대역폭을 말한다.
내가 찾고자 하는 파일이 누가 가지고 있는 지 알고 있다면 굳이 P2P는 필요하지 않을 것이다.

하지만 이러한 희생을 줄이는 것이 보다 좋을 것이라는 생각이 든다. 그런 점에서 내가 생각하는 가장
이상적인 P2P는 e-Donkey라고 생각 되어진다. 물론 지금의 e-Donkey는 아니다. 내가 생각하는 부분으로
고쳐져야 겠지. 하지만 지금의 e-Donkey처럼 개인이 서버를 가질 수 있고 또한 이 서버를 가지고 찾는
다면 불필요한 대역폭은 줄어들 것이고 분산된 서버를 하나의 순수 P2P로 묶고 서버에서 클라이언트의
노드들을 수정해 준다면 가장 이상적이지 않을까? 라고 한 때 무신히 고민했다. 잡소리 이제 그만!!!!

== The Gnutella Protocol Document ==

The Gnutella Protocol Document

1. Protocol Specification

1.1 Gnutella란 Peer to Peer 의 분산 모델로서 Mesh구조의 네트워크망을 가지며
Query전송을 통해 네트워크내 파일의 검색과 다운로드를 가능하게 한다.

1.2 프로토콜 정의
5개의 Descriptor를 사용하고 TCP/IP 프로토콜과 ASCII Code를 기반으로
이용하여 통신이 이루어진다.
- 네트워크망 초기 진입 -
{{{~cpp Connection String : GNUTELLA CONNECTION//nn}}}
{{{~cpp Response Connection : GNUTELLA OKnn}}}
- Note
Note 1 : 모든 데이터 필드는 특별한 말이 없으면 리틀 엔디언
Note 2 : IP 주소는 IPv4 형식으로 쓰인다.
Note 3 : Protocol은 Header와 Payload로 구성
- 헤더
Descriptor ID (16 byte): 네트워크 상의 고유 식별자
Payload Descriptor (2 byte): 명령어의 식별자
TTL (1 byte): 네트워크의 Servent를 지날 때마다 감소하는 수 /
네트워크 부하를 줄이기 위해 쓰임
Hops (1 byte): 지나간 Servent수
Payload Length (4 byte): Header 다음에 따라오는 Descriptor 의 길이
Data가 스트림이기 때문에 공백이나 Pad Byte가 따라오지않는다.
Gnutella 프로토콜의 경우 synch를 맞추는 특별한 byte가 존재하지 않아
형식에 틀린 Descriptor는 폐기된다.

|| DescriptorID || Payload Descriptor || TTL || hops || PayloadLength ||
0 15 16 17 18 19 22

- 디스크립터 (Descriptor)
표1)
|| 색인 || 설명 ||
|| ping || 네트워크상의 호스트를 찾을 때 쓰인다. Payload가 없기 때문에 header의 Payload_Length = 0x00000000 로 설정된다. ||
|| pong || Ping을 받으면 주소와 기타 정보를 포함해 응답한다.Port / IP_Address / Num Of Files Shared / Num of KB Shared** IP_Address - Big endian ||
|| query ||네트워크상에서 검색에 쓰이고 검색 Minimum Speed ( 응답의 최소 속도 ), Search Criteria 검색 조건 ||
|| queryHit || 검색 Query 조건과 일치한 경우 QueryHit로 응답한다. Num Of Hits 조건에 일치하는 Query의 결과 수 Port / IP_Address (Big-endian) / Speed / Result Set File Index ( 파일 번호 ) File Size ( 파일 크기 )File Name ( 파일 이 / 더블 널로 끝남 ) Servent Identifier 응답하는 Servent의 고유 식별자 Push 에 쓰인다. ||
|| push || 방화벽이 설치된 Servent와의 통신을 위한 DescriptorServent Identifier / File Index / IP_Address(Big-endian)/Port||

1.3 명령어 라우팅
1. Pong 은 Ping이 왔던 같은 길을 따라 전송된다. 만약 DescriptorID가 n
인 Pong을 받았는 데 Descriptor ID가 n인 Ping 보지 못했다면 Ping을 보
낸 Servent는 네트워크 상에서 제거된 것을 의미한다.
2. QueryHit와 Query -
3. Push/QueryHit -
4. 전달 되었던 Ping과 Query를 제외하고 모든 Ping과 Query는 연결 된
모든 Servent에 전송된다.
5. TTL/Hop은 다른 Servent로 전송되기 전에 변경되며 후에 TTL이
0이면 다른 Servent로 전송되지 않는다.
6. 전에 전송된 Descriptor는 다시 전송되지 않는다. 네트워크 부하 줄임

1.4 파일 다운로드
QueryHit 명령어를 받으면 파일을 초기화 하고 다운로드를 시작한다.
이는 Gnutella 네트워크를 이용하는 것이 아니라 기존의 HTTP 프로토콜
을 이용하여 직접 파일이 전송된다.
GET/get///HTTP/1.0rn
Connection:Keep-Alivern
Range:bytes=0-rn
User-Agent:Gnutellarn3
rn
Range가 파일의 이어받기가 가능하게 함.
는 파일 번호이고 이는 QueryHit Result에 포함된 내용이다.
이와같은 HTTP 헤더를 받으면 서버는 다음과 같은 헤더를 보내준다.
HTTP 200 OKrn
Server:Gnutellarn
Content-type:application/binaryrn
Content-length:435678rn
rn
바로 다음에 데이터가 Content-length만큼 따라오게 된다.

1.5 방화벽이 설치된 Servents
방화벽으로 인해 직접 연결이 불가능한 경우 Push Descriptor를 보내고 라우팅을 통해 받은
QueryHit에 대한 응답으로 새로운 TCP/IP 연결이 생긴
다.
새롭게 연결 된 후
GIV:/nn 를 보내 파일
을 요청하면
GET/get///HTTP1.0rn
Connection:Keep-Alivern
Range:bytes=0-rn
User-Agent:Gnutellarn3
rn
과 같은 HTTP GET request형식으로 응답을 하며 파일을 전송한다.
그러나 Push Descriptor조차 보내지 못하면 파일전송은 불가능하다.

1.6 확장된 Gnutella 프로토콜
기존의 Gnutella가 다른 프로그램(BearShare) 에 의해 서비스 되면서
확장된 프로토콜 이 필요하게 되었다. 이를 Triler라고 하며 QueryHit 의
ResultSet 마지막 더블널 과 Servent ID사이에 들어간다.
- Trailer
VendorCode(3byte) OpenDataSize(1byte) OpenData(2byte) PrivateData(n)

2. Gnutella Core Code
2.1 Data Structure
File Name : Packet.Cpp
Common IP / ExIP / Node / NodeEx
GnutellaPacket packet_Header / packet_Ping / packet_Pong
packet_Push / packet_Query / packet_QueryHit

2.2 Class Hierarchal Diagram

3. Gnucleus Technical Description
Gnuclues는 Gnutella 프로젝트 중 OpenSoure로 실제 인터페이스 부분이 열악하다.
하지만 Gnucleus의 Core 코드 부분의 Docunment가 가장 잘 나와있고 실제로
Compile / Execute 가능한 Code를 손에 얻을 수 있는 프로그램이다. 물론
지금 상태는 버전의 호환성으로 인해 Gnucleus node에 실제 노드에 접속하는 것이
어렵지만 같은 버전 사이의 접속은 가능하므로 인터페이스 부분을 수정한다면
보다 좋은 프로그램으로 변형할 수 있을 것 같다.
또한 Entica에서 필요로하는 Search / MultiThreadDownloader를 지원하며
또한 가장 기본적인 기능을 구현하여 불필요한 소스코드가 적다는 장점도 있다.
이런 이유로 다른 몇몇 Gnutella 프로그램도 Gnucleus를 기반으로 작성 되어졌다.

4. Note
servent : server 와 client 의 합성어
little endian byte : 작은 쪽 (바이트 열에서 가장 작은 값)이 먼저 저장되는 순서
descriptor : 패킷이 갖는 의미
payload : 패킷 갖는 데이타

5. 참고 URL

http://www.gnucleus.com/ (Gnucleus 프로그램)

http://www.sourceforge.net/ (Gnutella Clone 프로그램)

http://www.gnutelladev.com/source/gnucleus0.html (소스코드)

CVS// http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/gnucleus/(최근의 소스코드)


== 기타 코드에 관한 설명 ==
----

Gnucleus에서 다운로드 받는 방법에 대한 설명
{{{~cpp
void CSearchResults::OnButtonDownload()
{
std::list::iterator itGroup;
POSITION pos = m_lstResults.GetFirstSelectedItemPosition();

while(pos)
{
int nItem = m_lstResults.GetNextSelectedItem(pos);
ResultGroup* pGroup = (ResultGroup*) m_lstResults.GetItem(nItem);

if(pGroup)
RelayDownload(*pGroup);
}
}
}}}
에서 다운로드 버튼을 누르면 결과 그룹중에서 pos를 기억하고 이 pos를 이용해 다운받을
파일을 선택하고 그 그룹의 결과값을 RelayDownload 함수의 전달인자로 보낸다.
{{{~cpp
void CSearchResults::RelayDownload(ResultGroup &Item) 에서는
CGnuDownloadShell* Download = new CGnuDownloadShell(m_pComm);
}}}
에서와 같이 새로운 다운로드 쉘을 만들고
{{{~cpp
m_pComm->m_DownloadList.push_back(Download);
}}}
와 같이 m_DownloadList에 Download 객체를 삽입하고 CGnuControl에서 제어하게 만든다.
{{{~cpp
Download->m_Name = Item.Name;
Download->m_Search = ReSearch;
Download->m_FileLength = Item.Size;
Download->m_AvgSpeed = Item.AvgSpeed;
}}}
같이 초기화를 한다.
{{{~cpp
// Add hosts to the download list
for(int i = 0; i < Item.ResultList.size(); i++)
Download->AddHost( Item.ResultList[i] );
}}}
처럼 DownloadShell에 AddHost함수를 통해 Item의 모든 Host를 다운로드 에 넣는다.
그러면 View 에 Download에 관한 페이지를 업데이트하고 DownloadShell의 생성자가 실행이 된다.


CGnuControl에서의 void CGnuControl::ManageDownloads()에 의해 제어된다.
void CGnuDownloadShell::Start() 로 다운로드가 시작이 되고 실제적인 다운로드는 CGnuDownload에서 이루어지면 쉘에서는 Timer()에서 CheckCompletion()로 완료 되었는 지 확인을 하게 되고 AttachChunk2Chunk 와 AttachChunk2Partial로 부분부분 완료된 Chunk들을 결합해 주는 역활을 하게 된다.
실제적으로 하나의 Host마다 CGnuDownload 클래스를 갖게 되며 데이타를 받는 소켓이 된다m_StartPos가 받기 시작하는 Chunk의 시작을 나타내며 ReadyFile()에서는 전의 받던 파일이 있는 지 조사후에 File을 연다.
StartDownload() 함수에서 다운로드를 시작하며 GetStartPos() 를 통해 Chunk가 다운로드가 시작할 m_pChunk->m_StartPos의 위치를 알게 한다.
{{{~cpp
m_StartPos = m_pShell->m_BytesCompleted + ((m_pShell->m_FileLength - m_pShell->m_BytesCompleted) / 2);
m_pChunk->StartPos = m_StartPos;
m_pChunk->FileLength = m_pShell->m_FileLength - m_StartPos;
}}}
공식으로 Chunk의 시작위치를 구한다.
SendRequest() 에서 HTTP/GET 형식으로 헤더를 보내 받고자 하는 데이타를 요청한다
OnReceive(int nErrorCode) 에서 Content-length 만큼의 버퍼 데이타를 받아 청크와 연결 시킨다.
이어 받기를 할때에는 파일의 끝에서 -4096만큼 얻고 m_Verification 블럭의 4096크기 만큼 비교를 한 후에 이어받기를 시작한다.
새로운 청크를 만드는 조건은 이미 완료된 청크의 남은 부분이 EmptySize > 16384 보다 커야
한다는 것이다.
소스는 다음과 같고
{{{~cpp
// Reset m_pChunk because this can be called multiple times
if(m_pChunk)
{
bool destroy = true;
for(int i = 0; i < m_pShell->m_ChunkList.size(); i++)
if(m_pShell->m_ChunkList[i] == m_pChunk)
destroy = false;

if(destroy)
delete m_pChunk;

m_pChunk = NULL;
}
}}}
부분은 소켓의 청크중에 지금의 청크가 없다면 지금 받은 청크는 끝마친 것으로
생각하고 m_pChunk = NULL로 만든다




----

Gnucleus에서 프로토콜 통신

GnuCreateGuid(&Guid) // DescriptorID 생성
라우팅시 연결된 모든 nodeList에서 key->Origin를 찾아내어 key->Origin를 제외한 모든 node에 받은 pong 또는 queryHit를 전달
- Search
{{{~cpp
int length = 25 + m_Search.GetLength() + 1;
pNode->SendPacket(m_Packet, length, PACKET_QUERY, true);
}}}
- Result Set
{{{~cpp
// Extract results from the packet
while(HitsLeft > 0 && NextPos < Length - 16)
{
Result Item;

memcpy(&TempX, &Packet[NextPos], 4);
Item.FileIndex = makeD( flipX(TempX));
memcpy(&TempX, &Packet[NextPos + 4], 4);
Item.Size = makeD( flipX(TempX));

Item.Host = QueryHit->Host;
Item.Port = QueryHit->Port;
Item.Speed = makeD( flipX(QueryHit->Speed));

Item.Firewall = Firewall;
Item.Busy = Busy;
Item.Stable = Stable;
Item.ActualSpeed = ActualSpeed;

if(ExtendedPacket)
Item.Vendor = Vendor;

Item.Origin = Log->Origin;
memcpy(&Item.PushID, &Packet[Length - 16], 16);
Item.Distance = Log->Header->Hops;

// Get Filename
for(i = NextPos + 8; Packet[i] != 0; i++)
if(i < Length - 16)
Item.Name += (char) Packet[i];
else
break;

// Pass any data between double null
while(Packet[++i] != 0)
if(i > Length - 16)
break;


Item.NameLower = Item.Name;
Item.NameLower.MakeLower();
Item.Icon = m_pDoc->GetIconIndex(Item.NameLower);

m_WholeList.push_back(Item);

// Screen Item to user's preferences
if(Inspect(Item))
{
m_CurrentList.push_back(Item);
m_tabResults->UpdateList( AddtoGroup(Item) );
}

// Check for end of reply packet
if(i + 1>= Length - 16)
HitsLeft = 0;
else
{
HitsLeft--;
NextPos = i + 1;
}
}

}}}
패킷의 packet_QueryHit 에서 ResultSet을 추출하여 Item Vector에 넣어준다.
{{{~cpp
void CGnuNode::Recieve_Ping(packet_Ping* Ping, int nLength)
key_Value* key = m_pComm->m_TableRouting.FindValue(&Ping->Header.Guid);
}}}
통해 받았던 핑인지 검사하고 if(key == NULL) 받았던 핑이 아니라 새로운 핑이라면 m_pComm->m_TableRouting.Insert(&Ping->Header.Guid, this) 처럼 라우팅 테이블에 넣고 Pong을 보내준다.

----

방화벽이 설치된 경우의 자세한 설명
{{{~cpp
UINT AttemptPort = pPrefs->m_ForcedPort ? pPrefs->m_ForcedPort : pPrefs->m_LocalPort;
AttemptPort += rand() % 99 + 0;
}}}
Firewall에 있을 경우 이런 방법으로 포트를 열지 못하면 랜덤한 포트를 부여 ForcedPort로 접속 Attempts < 3 만큼 시도를 한다.
그리고 PUSH를 Route PUSH를 통해 보내 그누텔라 default 포트가 아닌 열 수 있는 포트로 직접연결을 한다.
만약 상대방 서버가 FireWall에 있다면 QueryHit중의 bool Firewall;필드가 True가 되므로 이에 대한 응답으로
{{{~cpp
Item.Host = QueryHit->Host; Item.Port = QueryHit->Port;
}}}
에 해당하는 Port로 Download를 한다.

----

== Thread ==
TRACKBACK 0 AND COMMENT 0
HTTP 프락시 작성기

HTTP를 이용한 프락시 서버의 목적은 기본적으로 공용 캐쉬이다. 여기에 그룹 보안 및 미들웨어 수준의 통합이 이루어지면 이 것이 바로 상용 프락시가 되는 것이다.

이번에 작성한 프락시는 가장 단순한 형태로 구현하기로 목표를 잡았다.


프로그램에 대한 접근을 한 방식은 다음과 같다.

1. 브라우저와 소캣을 통해 브라우저의 Proxy Server 로의 요청 메시지를 분석한다.

2. Proxy Server 와 웹 서버 단의 메시지를 분석한다.

3. 분석된 서로간의 메시지를 테스트 하면서 동작이 어떤 식으로 연계되는지 확인하고 간단한 HTTP replay 서버를 실 코드로 작성한다. (멀티 쓰레드 기반)

4. 웹 서버에서 브라우저로 보내는 응답 메시지를 Proxy Server 에서 수신, 파일로 저장하는 실 코드를 작성한다.

5. 저장된 파일을 관리할 수 있는 인덱스 파일의 스키마를 생각한다. 스키마는 최대한 단순해야하며, 가능하면 plain text 를 이용. 차후 프로그램의 테스트에 단순 에디터의 사용만으로 테스팅이 가능하도록 함.

6. 구성된 스키마를 바탕으로 validate 를 결정할 수 있는 프로시져, 모듈을 작성한다. (Validate 라함은 실제 캐쉬의 동작방식을 함께 포함하는 개념이다. 따라서 이 정도로 프로젝트를 진행했다면 캐쉬 방법에 대해서 한번쯤 알아보고 자신에게 적합한 방식을 선택한다.)

7. 완성된 모듈을 현재까지 작업한 Proxy Server 와 통합한다.


상기 과정을 통해서 전체적인 프락시 서버를 완성하는 것이 가능하다.

프로젝트의 난이도는 중간정도.
TRACKBACK 0 AND COMMENT 0

다중 사용자의 connect 를 처리하기 위한 방법은 총 3가지의 방식으로 구분한다.

1. 유닉스 호환환경에서 제공하는 fork() 를 이용한 다중 프로세스
2. IO 멀티플렉싱을 이용한 다중 연결
3. 멀티 쓰레드를 이용한 다중 연결

3가지의 방법은 어떤 것이 좋다 나쁘다고 할 것이 아니고 적당한 상황하에서 적정한 기술을 이용하는 것이 관건이라고 할 수 있을 것이다.

1. fork() 이용 소스
[CODE] /** 멀티 프로세스를 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #define BUFFSIZE 30 void error_handling(const char* message); void z_handler(int sig); int main(int argc, char **argv) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; struct sigaction act; int addr_size, str_len, state; pid_t pid; char message[BUFFSIZE]; if(argc!=2) { printf("USAGE: %s <port>\n", argv[0]); exit(1); } act.sa_handler = z_handler; sigemptyset(&act.sa_mask); act.sa_flags=0; state = sigaction(SIGCHLD, &act, 0); if (state != 0) { puts("sigaction() error!"); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); while(1) { addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &addr_size); if (clnt_sock == -1) continue; if ((pid ==fork()) == -1) {   close(clnt_sock);   continue; } else if (pid >0) {   puts("connection success");   close("clnt_sock");   continue; } else {   close(serv_sock);   while( (str_len = read(clnt_sock, message, BUFFSIZE)) != 0) {   write(clnt_sock, message, str_len);   write(1, message, str_len);   }   puts("connection closing");   close(clnt_sock);   exit(0); } } return 0; } void z_handler(int sig) { pid_t pid; int rtn; pid = waitpid(-1, &rtn, WNOHANG); printf("zombi process ID: %d\n", pid); printf("return data : %d\n", WEXITSTATUS(rtn)); } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]

2. select 이용 소스
[CODE] /** IO 멀티플렉싱을 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #define BUFFSIZE 100 void error_handling(const char* message); int main(int argc, char **argv) { int serv_sock; struct sockaddr_in serv_addr; fd_set reads, temps; int fd_max; char message[BUFFSIZE]; int str_len; struct timeval timeout; if (argc != 2) { printf("USAGE : %s <port>\n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) error_handling("bind() error"); if (listen(serv_sock, 5) == -1) error_handling("listen() error"); FD_ZERO(&reads); FD_SET(serv_sock, &reads); fd_max = serv_sock; while (1) { int fd, str_len; int clnt_sock, clnt_len; struct sockaddr_in clnt_addr; temps = reads; timeout.tv_sec = 5; timeout.tv_usec = 0; if (select(fd_max + 1, &temps, 0, 0, &timeout) == -1)   error_handling("select() error"); for (fd = 0; fd < fd_max+1; fd++) {   if(fd == serv_sock) {   clnt_len = sizeof(clnt_addr);   clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_len);   FD_SET(clnt_sock, &reads);   if (fd_max < clnt_sock)   fd_max = clnt_sock;   printf("client connection : file descriptor %d\n", clnt_sock);   }   else {   str_len = read(fd, message, BUFFSIZE);   if (str_len == 0) {   FD_CLR(fd, &reads);   close(fd);   printf("client closing: file descriptor %d\n", fd);     }   else {   write(fd, message, str_len);   }   } } } } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]
TRACKBACK 0 AND COMMENT 0

ARTICLE CATEGORY

분류 전체보기 (782)
Re: myself (441)
Favorite things (241)
CS&E (71)
Portfolio (22)
삼성SDS (0)

CALENDAR

«   2008/07   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

ARCHIVE