2009-09-23 46 views
13

Tôi đang tạo phần mềm máy chủ tùy chỉnh của riêng mình cho trò chơi bằng Java (phần mềm trò chơi và phần mềm máy chủ gốc được viết bằng Java). Không có bất kỳ tài liệu giao thức nào có sẵn, vì vậy tôi phải đọc các gói tin với Wireshark.Cập nhật cửa sổ TCP là gì?

Trong khi máy khách kết nối máy chủ, gửi tệp cấp ở định dạng Gzip. Vào khoảng 94 gói tin gửi mức độ, máy chủ của tôi treo máy khách với một ArrayIndexOutOfBoundsException. Theo tệp chụp từ máy chủ gốc, nó sẽ gửi một bản cập nhật TCP Window vào thời điểm đó. Cập nhật Cửa sổ TCP là gì và tôi sẽ gửi một bản cập nhật bằng cách sử dụng SocketChannel như thế nào?

Trả lời

50

Cửa sổ TCP được sử dụng để kiểm soát luồng giữa các đồng nghiệp trên kết nối. Với mỗi gói ACK, một máy chủ sẽ gửi một trường "kích thước cửa sổ". Trường này cho biết số lượng byte dữ liệu mà máy chủ lưu trữ có thể nhận được trước khi nó đầy. Người gửi không được phép gửi nhiều hơn số lượng dữ liệu đó.

Cửa sổ có thể đầy nếu khách hàng không nhận dữ liệu đủ nhanh. Nói cách khác, các bộ đệm TCP có thể lấp đầy trong khi ứng dụng đang làm một cái gì đó khác ngoài việc đọc từ ổ cắm của nó. Khi điều đó xảy ra, máy khách sẽ gửi một gói ACK với bộ bit "cửa sổ đầy đủ". Tại thời điểm đó, máy chủ được cho là dừng gửi dữ liệu. Bất kỳ gói nào được gửi đến máy có cửa sổ đầy đủ sẽ không nhận được không. Nếu một bộ đệm ở phía gửi cũng đầy, thì ứng dụng gửi sẽ chặn khi nó cố gắng ghi thêm dữ liệu vào ổ cắm. !)

Đây là ngăn xếp TCP. Nó có thể xảy ra vì nhiều lý do, nhưng cuối cùng nó chỉ có nghĩa là người gửi đang truyền nhanh hơn người nhận đang đọc.

Khi ứng dụng trên đầu nhận được quay lại để đọc từ ổ cắm, nó sẽ rút một số dữ liệu đệm, giúp giải phóng một số dung lượng.Người nhận sau đó sẽ gửi gói "cập nhật cửa sổ" để cho người gửi biết số lượng dữ liệu có thể truyền. Người gửi bắt đầu truyền dữ liệu đệm và lưu lượng truy cập sẽ lưu thông thường.

Tất nhiên, bạn có thể nhận được các quầy hàng lặp lại nếu máy thu luôn chậm.

Tôi đã diễn đạt điều này như thể người gửi và người nhận khác nhau, nhưng trên thực tế, cả hai đồng nghiệp đang trao đổi cập nhật cửa sổ với mọi gói ACK và cả hai bên đều có thể lấp đầy cửa sổ.

Thông báo chung là bạn không cần phải gửi gói cập nhật cửa sổ trực tiếp. Nó sẽ thực sự là một ý tưởng tồi để giả mạo một lên.

Về ngoại lệ bạn đang xem ... nó không có khả năng gây ra hoặc bị ngăn chặn bởi gói cập nhật cửa sổ. Tuy nhiên, nếu khách hàng không đọc đủ nhanh, bạn có thể mất dữ liệu. Trong máy chủ của bạn, bạn nên kiểm tra giá trị trả về từ các cuộc gọi Socket.write() của bạn. Nó có thể nhỏ hơn số byte bạn đang cố gắng viết. Điều này xảy ra nếu bộ đệm truyền của người gửi đầy, điều này có thể xảy ra trong một gian hàng TCP. Bạn có thể bị mất byte.

Ví dụ: nếu bạn đang cố gắng viết 8192 byte với mỗi cuộc gọi để viết, nhưng một trong các cuộc gọi trả về 5691, thì bạn cần phải gửi 2501 byte còn lại vào cuộc gọi tiếp theo. Nếu không, máy khách sẽ không thấy phần còn lại của khối 8K đó và tệp của bạn sẽ ngắn hơn ở phía máy khách hơn là phía máy chủ.

+3

Lỗi-fu của tôi cho tôi biết đoạn cuối này rất có khả năng đã đóng đinh vấn đề. – caf

+1

Giải thích tuyệt vời, cảm ơn! Chính xác những gì tôi cần. Tôi nghĩ rằng tôi đã tìm thấy nguyên nhân của ngoại lệ - khách hàng đã dự kiến ​​dữ liệu trong một hình thức khác, hơi dài hơn so với những gì tôi đang gửi. – phpscriptcoder

+0

+1 để có giải thích chi tiết! – Izza

7

Điều này xảy ra thực sự sâu trong ngăn xếp TCP/IP; trong ứng dụng của bạn (máy chủ và máy khách), bạn không phải lo lắng về các cửa sổ TCP. Lỗi phải là một thứ khác.

2

Cập nhật cửa sổ TCP phải làm với việc truyền đạt kích thước bộ đệm có sẵn giữa người gửi và người nhận. Một ArrayIndexOutOfBoundsException không phải là nguyên nhân gây ra điều này. Rất có thể là mã đang chờ đợi một số loại dữ liệu mà nó không nhận được (có thể khá tốt trước thời điểm này mà bây giờ nó chỉ là tham chiếu). Mà không nhìn thấy mã và theo dõi ngăn xếp, nó thực sự là khó để nói bất cứ điều gì nhiều hơn nữa.

+0

Cảm ơn sự trợ giúp. Dấu vết ngăn xếp không phải là quá hữu ích, vì mã khách hàng bị làm nhiễu nên tất cả các lớp và phương thức đều là các chữ cái đơn ... Cần nghiên cứu thêm! – phpscriptcoder

+0

@phpscriptcoder: Có thể bạn sẽ nhận được (các) lập trình viên ban đầu bị sa thải ... –

0

Bạn có nhận được bất kỳ details nào với số exception không?

Người ta không có khả năng liên quan đến các gói tin TCP Window Update
(có bạn nhìn thấy nó lặp lại chính xác cho nhiều trường hợp?)

Nhiều khả năng liên quan đến mã xử lý của bạn mà làm việc trên các dữ liệu nhận được.

0

Điều này thường chỉ là kích hoạt chứ không phải nguyên nhân gây ra sự cố của bạn.

Ví dụ: nếu bạn sử dụng bộ chọn NIO, bản cập nhật cửa sổ có thể kích hoạt báo thức của kênh viết. Điều đó lần lượt kích hoạt logic bị lỗi trong mã của bạn.

Nhận stacktrace và nó sẽ cho bạn thấy nguyên nhân gốc rễ.

2

TCP WindowCập nhật - Điều này cho biết rằng phân khúc là phân đoạn WindowUpdate thuần túy. WindowUpdate xảy ra khi ứng dụng ở phía bên nhận đã tiêu thụ dữ liệu đã nhận từ bộ đệm RX khiến lớp TCP gửi WindowUpdate sang phía bên kia để cho biết hiện có nhiều không gian hơn trong bộ đệm. Thường thấy sau khi một điều kiện TCP ZeroWindow đã xảy ra. Khi ứng dụng trên máy thu lấy dữ liệu từ bộ đệm TCP, do đó giải phóng không gian, người nhận phải thông báo cho người gửi rằng điều kiện TCP ZeroWindow không còn tồn tại bằng cách gửi một TCP WindowUpdate quảng cáo kích thước cửa sổ hiện tại.

https://wiki.wireshark.org/TCP_Analyze_Sequence_Numbers

Các vấn đề liên quan