2012-03-25 29 views
7

Tôi đang thực hiện một chương trình giao tiếp với một số bệnh nhân theo dõi bằng cách sử dụng ổ cắm C. Tôi đang sử dụng ổ cắm ít kết nối (UDP) để giao tiếp với thiết bị. Nhưng có endianness mis-match giữa máy tính và điện thoại của tôi và cho đến nay tôi đã làm điều này để có được câu trả lời phân tích cú pháp từ theo dõi bệnh nhân:Endianness and Socket Programming in C

recvfrom(int socket, char *buffer, size_t length, int flags, 
      struct sockaddr *address, socklen_t *address_len); 

Sau đó, tôi đã đúc bộ đệm trực tiếp đến cấu trúc và sử dụng ntohs và ntohl để thay đổi thứ tự byte, ví dụ:

struct A * a = (struct A *)buffer; 
Struct A b; 
b.v1 = ntohs(a->v1); 
b.v2 = ntohl(a->v2); 

Sau khi đọc một vài ví dụ qua internet, tôi đã tìm ra cách tiếp cận này sai do đệm phụ thuộc vào trình biên dịch. Nhưng tôi không chắc lắm. Tôi cần cách đơn giản để un-marshall một bộ đệm cho một cấu trúc C với endiannes chính xác. Cấu trúc mà tôi nhận được có thể có chiều dài không thể đoán trước và ít phức tạp. Tôi cần cách tiếp cận nhanh chóng và dễ dàng để thực hiện việc không sửa đổi.

Tôi không kiểm soát người gửi. Người gửi nằm trong thứ tự byte mạng. Câu hỏi của tôi chỉ là: - Có an toàn khi bỏ một bộ đệm vào một cấu trúc và sau đó sử dụng ntohs và ntohl trên cấu trúc đúc này để tạo bản sao thứ tự byte lưu trữ của cấu trúc này? Đó có phải là cách tiếp cận nhanh nhất không? Nếu không, thì điều gì có thể là cách tiếp cận nhanh nhất?

+0

làm bạn kiểm soát người gửi là tốt? Họ có gửi gói tin theo thứ tự byte mạng không? – hroptatyr

+0

Tôi nghĩ rằng giải pháp của bạn đã đúng, bạn có thể sử dụng '__attribute __ ((đóng gói))' hoặc 'aligned (x)' để đảm bảo trình biên dịch không làm hỏng cấu trúc của bạn. – hroptatyr

+0

chuyển đổi sang thứ tự byte mạng khi đặt dữ liệu trên dây và chuyển đổi sang thứ tự máy chủ khi tháo dây. –

Trả lời

3

Trước hết, vì a là apointer, mã của bạn nên ở mức tối thiểu làm điều này ...

b.v1 = ntohs(a->v1); 
b.v2 = ntohl(a->v2); 

Thứ hai, câu trả lời phụ thuộc vào hoàn cảnh và đặc điểm kỹ thuật của màn hình bệnh nhân. Ai viết mã cho màn hình bệnh nhân? Có một đặc điểm kỹ thuật cho nó? Bạn đang sử dụng kiến ​​trúc máy nào (trong trường hợp bạn biết), bạn chỉ đang xử lý một mô hình hoặc có nhiều phiên bản của màn hình - bạn có thể thay đổi màn hình, v.v.

Im sẽ giả định rằng bạn không thể thay đổi màn hình và thứ tự byte được ghi ở đâu đó - và bạn có thể phải tạo các gói giải nén/gói của riêng bạn bằng cách thực hiện xử lý byte và thao tác bit - trừ khi bạn biết định dạng chính xác phù hợp với thứ tự "mạng" - và phần đệm của các cấu trúc giống nhau trong bộ đệm mạng.

Vì vậy, một cái gì đó như;

void unpack(struct *b, unsigned char *buffer) 
{ 
    b->v1 = (buffer[0] <<8)|(buffer[1]); 
   b->v2 = (buffer[2] <<24)|(buffer[3] <<16)|(buffer[4] <<8)|(buffer[5]); 
    etc.... 
}    

hoặc như thế này nếu bạn thích bạn ntohX;

void unpack(struct *b, unsigned char *buffer) 
{ 
    b->v1 = ntohs(buffer+0); 
   b->v2 = ntohl(buffer+2); 
    etc.... 
}    

Tuy nhiên nếu bạn làm kiểm soát mã màn hình, sau đó sử dụng một công cụ như protocol buffers sẽ thoát khỏi tất cả sự phức tạp của việc thao tác bit và lo lắng về lệnh byte ....

+0

Có, cảm ơn bạn đã trả lời. Tôi đã viết mã trên ví dụ làm sai lầm nhỏ. :) Có thể giải thích những loại thông số kỹ thuật bạn đang nói về? – Shivam

+0

Đặc điểm kỹ thuật cho việc bố trí dữ liệu đến/từ màn hình bệnh nhân .... – Soren

+0

Cảm ơn bạn. Điều này giải quyết được vấn đề của tôi.Nhưng vẫn còn, thay vì cứng mã hóa tất cả các thao tác bit, tôi có thể chỉ cần đưa bộ đệm vào cấu trúc của tôi và sử dụng ntohs trên các thuộc tính riêng lẻ của cấu trúc? Ngoài ra, cách tiếp cận trên có độc lập với tính endianness của máy tính chủ không? – Shivam