Gửi tin broadcast hay multicast phải dùng UDP
 Có thể dùng UDP với các ứng dụng với yêu cầu -trả lời đơn giản
 Có thể dùng UDP vỚI các ứng dụng LAN
 Băng thông lớn, ít lỗi 
 Nên dùng UDP với truyền tin đa phương tiện
 Điều khiển luồng?
 Dùng TCP với việc truyền dữ liệu lớn
 TFTP (Trivial File Transfer Protocol) là một ngoại lệ
              
                                            
                                
            
 
            
                 28 trang
28 trang | 
Chia sẻ: Mr Hưng | Lượt xem: 1511 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang nội dung tài liệu Lập trình UDP socket nâng cao, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Lập trình UDP socket nâng cao
TS. Nguyễn Hoài Sơn
Bộ môn mạng và Truyền thông máy tính,
Đại học Công nghệ, Đại học QG Hà Nội
UDP hay TCP ?
 Gửi tin broadcast hay multicast phải dùng UDP
 Có thể dùng UDP với các ứng dụng với yêu cầu -
trả lời đơn giản
 Có thể dùng UDP vỚI các ứng dụng LAN
 Băng thông lớn, ít lỗi 
 Nên dùng UDP với truyền tin đa phương tiện
 Điều khiển luồng?
 Dùng TCP với việc truyền dữ liệu lớn
 TFTP (Trivial File Transfer Protocol) là một ngoại lệ
Vấn đề với UDP
 Làm thế nào để lấy địa chỉ IP đích?
 Địa chỉ IP đích có thể là địa chỉ unicast hoặc địa 
chi multicast
 Làm thế nào biết và xử lý trong trường hợp 
gói tin UDP lớn hơn kích thước buffer?
 Làm thế nào để đảm bảo tính tin cậy khi 
đường truyền có lỗi
 Acknowledgement, timeout, gửi lại
Lấy cờ hiệu, địa chỉ IP đích và số hiệu 
giao diện mạng
 Dùng sendmsg và recvmsg để lấy
 cờ hiệu từ socket
 các dữ liệu phụ thuộc như địa chỉ IP và số hiệu 
giao diện đích trong trường hợp có nhiều giao 
diện mạng
Remind: sendmsg and recvmsg
struct msghdr { 
void *msg_name; /* protocol address */ 
socklen_t msg_namelen; /* size of protocol address */ 
struct iovec *msg_iov; /* scatter/gather array */ 
int msg_iovlen; /* # elements in msg_iov */ 
void *msg_control; /* ancillary data (cmsghdr struct) */ 
socklen_t msg_controllen; /* length of ancillary data */
int msg_flags; /* flags returned by recvmsg() */ 
}; 
#include 
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
Both return: number of bytes read or written if OK, –1 on error
Remind: sendmsg and recvmsg (2)
 thiết lập cờ chức năng cho việc xuất nhập dữ liệu
 MSG_DONTROUTE: bỏ qua truy vấn bảng định tuyến
 MSG_DONTWAIT: không chờ khi xuất nhập dữ liệu
 MSG_OOB: gửi và nhận dữ liệu ngoài luồng (out-of-band)
 MSG_PEEK: kiểm tra dữ liệu vào nhưng vẫn giữ nguyên 
dữ liệu trong buffer
 MSG_WAITALL: đợi tất cả dữ liệu yêu cầu
 Cờ chức năng trả về bởi hàm recvmsg
 MSG_BCAST
 MSG_MCAST
 MSG_TRUNC
Remind: Sau khi hàm recvmsg trả kết quả
về
Ví dụ: hàm recvfrom_flags
 ssize_t recvfromflags(int fd, void *ptr, size_t nbytes, int 
*flagsp, SA *sa, socklen_t *salenptr, struct 
unp_in_pktinfo *pktp) 
 struct unp_in_pktinfo 
{ 
struct in_addr ipi_addr; /* destination IPv4 address */ 
int ipi_ifindex; /* received interface index */ 
};
 Trả về:
 Giá trị của msg_flags được trả về bởi hàm recvmsg
 Địa chỉ đích của gói tin nhận được (sử dụng tùy biến socket 
IP_RECVDSTADDR)
 Số hiệu của giao diện nhận gói tin (sử dụng tùy biến socket 
IP_RECVIF)
Dữ liệu phụ thuộc
 Gửi và nhận bằng thành phần msg_control và msg_controllen của 
cấu trúc msghdr với hàm sendmsg và recvmsg
 chứa một hoặc nhiều đối tượng dữ liệu phụ thuộc
 each one begins with a cmsghdr structure
 struct cmsghdr { 
socklen_t cmsg_len; /* length in bytes, including this structure */ 
int cmsg_level; /* protocol family */ 
int cmsg_type; /* protocol-specific type */ 
/* followed by unsigned char cmsg_data[] */ 
}; 
Dữ liệu phụ thuộc chứa hai đối tượng dữ
liệu
Các hàm macros để đơn giản hóa xử lý 
dữ liệu phụ thuộc
#include 
#include 
/* for ALIGN macro on many implementations */
struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *mhdrptr) ;
Returns: pointer to first cmsghdr structure or NULL if no ancillary data
struct cmsghdr *CMSG_NXTHDR(struct msghdr *mhdrptr, struct cmsghdr *cmsgptr) ;
Returns: pointer to next cmsghdr structure or NULL if no more ancillary data objects
unsigned char *CMSG_DATA(struct cmsghdr *cmsgptr) ;
Returns: pointer to first byte of data associated with cmsghdr structure
unsigned int CMSG_LEN(unsigned int length) ;
Returns: value to store in cmsg_len given the amount of data
unsigned int CMSG_SPACE(unsigned int length) ;
Returns: total size of an ancillary data object given the amount of data
recvfrom_flags function (2)
 advio/recvfromflags.c
Dữ liệu phụ thuộc kiểu IP_RECVIF
Hàm dg_echo với recvfrom_flags
 advio/dgechoaddr.c
Chia nhỏ gói tin UDP
 Khi nhận một gói tin UDP lớn hơn kích thước buffer, 
hệ thống có thể xử lý theo các cách sau tùy thuộc vào 
từng OS
 Bỏ phần dữ liệu vượt quá kích thước buffer, và trả về 
cờ MSG_TRUNC cho tiến trình xử lý
 recvmsg thiết lập cờ MSG_TRUNC trong msg_flags
của cấu trúc msghdr
 Bỏ phần dữ liệu thừa và không thông báo cho tiến 
trình xử lý
 Giữ phần dữ liệu thừa và trả về ở lần đọc dữ liệu 
socket sau đó
=> cần thiết lập kích thước buffer lớn hơn kích thước lớn 
nhất của gói tin UDP có thể nhận được một byte
Tạo tính tin cậy cho ứng dụng UDPs
 Thực hiện 2 yêu cầu
 Số thứ tự (Sequence numbers): Bên nhận xác nhận số 
thứ tự của thông báo nhận được
 Client thêm số thứ tự vào mỗi thông báo yêu cầu và máy chủ 
gửi lại số thứ tự này trong thông báo trả lời
 Timeout và gửi lại: khôi phục các gói tin bị mất mát 
 Gửi thông báo yêu cầu và đợi trong N giây
 Nếu không có thông báo trả lời, gửi lại và đợi thêm N giây
 Lặp lại nhiều lần
Tạo tính tin cậy cho ứng dụng UDPs (2)
 Làm thế nào để xác định N thích hợp?
 RTT trong mạng LAN và WAN là khác nhau
 RTT giữa máy khách và máy chủ có thể thay đổi 
nhanh chóng
 Cần tính toán RTT thực sự
=> Giải pháp từ [Jacobson 1988] 
g = 1/8, h = 1/4
Vấn đề không rõ ràng khi gửi lại
Thông báo yêu cầu bị mất?
Thông báo trả lời bị mất?
Khoảng RTO là quá nhỏ?
RTT là bao nhiêu?
Giải pháp
 Thêm nhãn thời gian vào mỗi thông báo và 
máy chủ cũng phải gửi lại nhãn thời gian này
 Tính toán RTT bằng thời gian nhận gói tin trừ 
đi nhãn thời gian ghi trong gói tin
=> Hàm dg_send_recv
struct rtt_info 
 struct rtt_info {
float rtt_rtt; /* RTT gần nhất, đơn vị giây */
float rtt_srtt; /* Ước lượng RTT, đơn vị giây */
float rtt_rttvar; /* Ước lượng độ lệch trung bình, đơn vị 
giây */
float rtt_rto; /* RTT hiện tại, đơn vị giây */
int rtt_nrexmt; /* số lần gửi lại: 0, 1, 2, ... */
uint32_t rtt_base; /* thời gian (giây) tính từ 1/1/1970 */
};
dg_send_recv function 
 rtt/dg_send_recv.c 
g = 1/8, h = 1/4
Các bước thực hiện
Khởi tạo đồng hồ đếm độ trễ 
Khởi tạo dữ liệu gửi msgsend
• Tiêu đề chứa sequence number và nhãn thời gian
Đặt tín hiệu chuông
• Thời gian đổ chuông ban đầu
= độ trễ ước lượng 
Chờ và nhận gói tin trả lời
Tính toán lại độ trễ ước lượng
alarm(rtt_star
t(&rttinfo))
rtt_init(&rtti
nfo)
rtt_stop(&rttinfo, 
rtt_ts(&rttinfo) -
recvhdr.ts)
timeout
Các hàm tính toán độ trễ
lib/rtt.c 
 rtt_init
 rtt_ts, rtt_newpack, rtt_start, rtt_stop
Xuất nhập dữ liệu I/O bằng 
điều khiển tín hiệu
Mô hình xuất nhập dữ liệu bằng điều 
khiển tín hiệu
recvfrom
application kernel
sigaction system call
datagram ready
copy datagram
copy complete
wait 
for
data
copy 
data
from 
kernel
to userprocess 
datagram
process 
continues
executing
return OK
establish
SIGIO signal
handler
deliver SIGIO
system call
process blocks 
while data is 
copied into 
application
buffer
return
signal 
handler
Các bước thực hiện xuất nhập dữ liệu 
bằng điều khiển tín hiệu
 Thiết lập hàm xử lý tín hiệu SIGIO 
 Thiết lập chủ sở hữu socket
 sử dụng lệnh F_SETOWN của hàm fcntl
 Cho phép xuất nhập dữ liệu bằng điều khiển 
tín hiệu
 sử dụng lệnh F_SETFL của hàm fcntl để thiết lập 
cờ O_ASYNC
SIGIO với UDP Sockets 
 Tín hiệu SIGIO được sinh ra khi
 Socket nhận được một gói tin
 Lỗi không đồng bộ xuất hiện tại socket
SIGIO với TCP Sockets 
 Nhiều điều kiện để tạo ra tín hiệu SIGIO 
 Một yêu cầu kết nối kết thúc tại socket lắng nghe
 Một yêu cầu kết nối được khởi tạo
 Một yêu cầu ngắt kết nối được hoàn thành
 Một nửa kết nối bị đóng
 Dữ liệu đến socket
 Dữ liệu được gửi từ socket
 Lỗi không đồng bộ xuất hiện
=> Ít sử dụng SIGIO với TCP socket
Máy chủ UDP Echo sử dụng SIGIO 
 sigio/dgecho01.c
 Đặt dữ liệu nhận được trong hàng đợi dữ liệu chờ 
xử lý
 Sau khi xử lý tín hiệu SIGIO, tăng biến đếm của 
hàng đợi nqueue
 Gửi lại dữ liệu nhận được khi biến đếm của hàng 
đợi khác 0
 Điều gì xảy ra nếu tín hiệu SIGIO không bị chặn 
trong khi chương trình kiếm tra biến nqueue ?
            Các file đính kèm theo tài liệu này:
 ltm_bai_5_advanced_udp_socket_2314.pdf ltm_bai_5_advanced_udp_socket_2314.pdf