2013-04-28 3 views
0

프로그램 용 소켓 관리자를 만들려고합니다.소켓 - 정확한 양의 데이터 받기

내 문제는 내가 소켓에서 버퍼에 정확한 양의 데이터를 검색해야합니다.

1)를 사용하여 정적 배열

같은 정적 버퍼가 나를 위해 작동 만들기,하지만 난 항상 데이터의 크기가 수신 할 수 알 수 없습니다.

ubyte[2] buffer; 
socket.receive(buffer); 

이 작동하지 않습니다

그래서 내 첫 번째 질문은
int size = buffer[0]; // for example ... 
ubyte[size] buffer2; // crash at compilation because size is not known 
socket.receive(buffer2); 

: 가 컴파일에서 크기를 모른 채 정적 배열을 할 수 있습니까?

동적 버퍼를 사용하는 방법을 검색했지만 다른 문제가 발생했습니다. 버퍼

ubyte[] buffer; 
socket.receive(buffer); 
ubyte[2] header = buffer[0..2]; 

이 작동하지만, 어떻게 메인 버퍼에서 추출 슬라이스를 제거 할 수 있습니다에서 데이터를 추출하기 위해 조각을 사용하여

2)?

Error: undefined identifier tuple

: 내가 모르는 나를 위해 작동 왜, 내가 컴파일에서이 오류가없는

buffer = remove(buffer,tuple(0,2)); 

않습니다 튜플로 std.algorithm에서 제거 기능을 사용하여,이 방법은 여기에 무슨 문제가 있습니까?

또한 비동기이기 때문에 소켓이 비 블로킹입니다. 소켓이 동시에 데이터를 푸시하려고하면 주 버퍼에서 제거를 수행하면 문제가 발생합니까?

나를 읽어 주셔서 감사합니다. 불쌍한 영어를 유감스럽게 생각하며, 저는 원어민이 아닙니다.

답변

2

경고 : 이전에는 std.socket을 사용하지 않았으므로 테스트되지 않았습니다.

import std.socket; 
import std.bitmanip; 

Socket socket = new Socket(AddressFamily.INET, SocketType.STREAM); 
// ... bind, connect, etc ... 
ubyte[2] header; 
socket.receive(header); 
ushort size = std.bitmanip.bigEndianToNative!ushort(header); 
ubyte[] content = new ubyte[size]; 
socket.receive(content); 
// ... do your stuff ... 

당신을 :

이것은 단지 당신이 원하는에서 추측하지만, 여기에 간다), I는 일반적으로 D와 C 소켓과 경험을 경험을 가지고 있지만 아직 함께 두 가지를 사용하지 않은 런타임시에도 들어오는 데이터의 크기를 어떻게 든 알 필요가 있습니다. 예제에서 크기는 스트림에서 나오는 첫 번째 2 바이트로 채워집니다. 이 정보를 사용하여 나머지 버퍼를 동적으로 할당합니다. 간단히하기 위해이 예는 동기식입니다. 콘텐츠가 채워질 때까지 수신은 차단됩니다. 이 예제는 반환 값을 뻔뻔스럽게 무시하지만 나쁘다.하지만 나는 단순하다.

비동기 통신을 수행 할 예정이므로 정의한 일부 조건이 충족되지 않으면 수신을 호출하여 버퍼를 채우거나 수신을 중단하는 자체 수신 함수를 작성해야 할 수 있습니다.

예제 1에서 문제는 예상 한 것입니다. 컴파일 타임에 크기를 몰라도 컴파일 할 때 (정적 배열) 크기를 조정할 방법이 없습니다.

질문에 대한 답은 아니오입니다. 컴파일 타임에 크기를 알지 못하고 정적 배열을 가질 수 없습니다.

예 2에서 "ubyte [] buffer;" receive에 건네지기 전에 null에 초기화됩니다. 아마 어설 션 충돌이나 segfault를 줄 것입니다. 대개 D의 함수가 버퍼를 요구할 때 메모리가 이미 할당 될 것으로 예상 할 것이다. 함수의 책임은 이미 할당 된 메모리를 원하는 모든 항목으로 채우는 것입니다. 유일한 예외는 인수가 ref, 예 : "void foo (ref ubyte [] buffer)"로 선언 된 경우 일 수 있습니다.이 함수는 사용자가 버퍼를 할당하지 않을 경우 버퍼를 할당합니다 (ref가 필요합니다). 그것을 달성하기 위해). 이것이 내 예제가 receive()에서 물건을 가져 오기 전에 "new ubyte [size]"평가를하는 이유입니다.

ubyte[] someArray = myArraySource(); 
ubyte[] header = someArray[0 .. 2]; 
someArray = someArray[2 .. $]; // Remove the "header" by slicing out everything else. 

이 당신의 마지막 질문에 대답하려면 : 아니, 그것은 문제가 발생하지 않아야

는 슬라이스에 대한 귀하의 질문에 대답하기 위해,이 배열을 주사위 할 수있는 간단한 방법입니다. 너 괜찮을거야.

세부 정보 : 소켓을 통한 양방향 통신의 경우 버퍼 조작이 소켓 자체에서 중요하지 않다고 생각합니다. 소켓은 해당 버퍼에 대한 참조를 유지하지 않으므로 소켓에 영향을주지 않고 기본 버퍼에서 "제거"할 수 있어야합니다. 당신이 그것을 할당했기 때문에 당신의 버퍼 (나는 희망한다). 이것은 소켓의 비동기적인 동기성에도 의존하지 않는다. 그것은 소켓이 당신의 버퍼를 그렇게 신경 쓰지 않는다는 것입니다. 바이트를 받거나 보낸 다음 소켓은 적어도 다음에 호출 될 때까지 작업을 완료했습니다.

희망 하시겠습니까?

+0

이 모든 정보를 제공해 주셔서 감사합니다. 나는 뭔가를 만들 수 있었지만 여전히 문제가 남아있다 :'ubyte [] content = new ubyte [size];는 내용의 길이를 같은 크기로 만들어 소켓에서받은 데이터의 길이를 더 이상 테스트 할 수 없다. 버퍼 ... 그것을 얻을 수있는 방법이 있습니까? – Munrek

+0

그래서 내 예제에서는 receive()를 두 번 호출했습니다. 한 번 길이를 가져오고 다시 한 번 크기가 지정된 데이터를 가져옵니다. 좋은 추측을하고 나중에 고칠 수 없다면 소켓 프로그래밍에서이 문제를 해결할 방법이 없습니다. 컴파일시에 추측 할 수 있다면, 다음 중 하나를 수행하십시오 :'ubyte [sizeGuess] buffer; 또는'ubyte [] buffer = new ubyte [sizeGuess];'. 예 : ubyte [] buf = new ubyte [sizeGuess]; auto nBytes = socket.receive (buf); assert (nBytes> 2); ushort size = bigEndianToNative! ushort (buf [0..2]); assert (nBytes - 2> = 크기); // 더 좋을 수있다;) buf = buf [2 .. size + 2]; – chadjoan

+0

이 주석에 코드 서식을 지정하는 것은 어렵습니다. [다음은 pastebin의 예입니다.] (http://dpaste.dzfl.pl/fff2cee8) – chadjoan