Điều kiện cuộc đua dữ liệu mạng từ địa ngục
Tôi đã viết một máy khách / máy chủ mạng (Windows XP / C #) để làm việc với một ứng dụng tương tự trên máy trạm thực sự cũ (Encore 32/77) được viết bởi một nhà phát triển khác.
Những gì ứng dụng đã làm về cơ bản là chia sẻ / thao tác dữ liệu nhất định trên máy chủ để kiểm soát quá trình máy chủ chạy hệ thống với giao diện người dùng màn hình cảm ứng đa màn hình dựa trên PC ưa thích của chúng tôi.
Nó đã làm điều này với cấu trúc 3 lớp. Quá trình truyền thông đọc / ghi dữ liệu đến / từ máy chủ, đã thực hiện tất cả các chuyển đổi định dạng cần thiết (endianness, định dạng dấu phẩy động, v.v.) và ghi / đọc các giá trị đến / từ cơ sở dữ liệu. Cơ sở dữ liệu hoạt động như một trung gian dữ liệu giữa các comms và UI màn hình cảm ứng. Ứng dụng của giao diện người dùng màn hình cảm ứng được tạo ra giao diện màn hình cảm ứng dựa trên số lượng màn hình được gắn vào PC (nó tự động phát hiện ra điều này).
Trong khung thời gian được cung cấp một gói giá trị giữa máy chủ và máy tính của chúng tôi chỉ có thể gửi tối đa 128 giá trị qua dây với thời gian trễ tối đa ~ 110ms mỗi chuyến khứ hồi (UDP được sử dụng với kết nối ethernet trực tiếp giữa các máy tính). Vì vậy, số lượng biến được phép dựa trên số lượng màn hình cảm ứng đính kèm được kiểm soát chặt chẽ. Ngoài ra, máy chủ (mặc dù có kiến trúc đa bộ xử lý khá phức tạp với bus bộ nhớ dùng chung cho điện toán thời gian thực) có sức mạnh xử lý khoảng 1/100 của điện thoại di động của tôi nên nó được giao nhiệm vụ xử lý ít nhất có thể và đó là máy chủ / client phải được viết thành hội đồng để đảm bảo điều này (máy chủ đang chạy mô phỏng toàn thời gian thực mà không thể bị ảnh hưởng bởi chương trình của chúng tôi).
Vấn đề là. Một số giá trị, khi được thay đổi trên màn hình cảm ứng sẽ không chỉ lấy giá trị mới nhập mà sẽ xoay vòng ngẫu nhiên giữa giá trị đó và giá trị trước đó. Điều đó và chỉ trên một vài giá trị cụ thể trên một vài trang cụ thể với sự kết hợp các trang nhất định từng thể hiện triệu chứng. Chúng tôi gần như đã bỏ lỡ vấn đề hoàn toàn cho đến khi chúng tôi bắt đầu chạy nó thông qua quy trình chấp nhận khách hàng ban đầu
Để xác định vấn đề, tôi chọn một trong các giá trị dao động:
- Tôi đã kiểm tra ứng dụng Màn hình cảm ứng, nó đang dao động
- Tôi đã kiểm tra cơ sở dữ liệu, dao động
- Tôi đã kiểm tra ứng dụng comms, dao động
Sau đó, tôi đã phá vỡ wireshark và bắt đầu giải mã thủ công các gói chụp. Kết quả:
- Không dao động nhưng các gói trông không ổn, có quá nhiều dữ liệu.
Tôi đã xem qua từng chi tiết của mã comms hàng trăm lần mà không tìm thấy lỗi / lỗi nào.
Cuối cùng, tôi bắt đầu bắn email cho các nhà phát triển khác hỏi chi tiết cách kết thúc của anh ta để xem liệu tôi có thiếu thứ gì không. Sau đó, tôi tìm thấy nó.
Rõ ràng, khi anh ta gửi dữ liệu, anh ta đã không xóa mảng dữ liệu trước khi truyền, vì vậy, về cơ bản, anh ta chỉ ghi đè lên bộ đệm cuối cùng được sử dụng với các giá trị mới ghi đè lên giá trị cũ, nhưng các giá trị cũ không được ghi đè vẫn được truyền đi.
Vì vậy, nếu một giá trị ở vị trí 80 của mảng dữ liệu và danh sách các giá trị được yêu cầu thay đổi thành nhỏ hơn 80 nhưng cùng một giá trị được chứa trong danh sách mới, thì cả hai giá trị sẽ tồn tại trong bộ đệm dữ liệu cho bộ đệm cụ thể đó thời gian nhất định.
Giá trị được đọc từ cơ sở dữ liệu phụ thuộc vào lát thời gian khi UI yêu cầu giá trị.
Việc sửa chữa rất đơn giản. Đọc số lượng mục đến trên bộ đệm dữ liệu (Nó thực sự được chứa như một phần của giao thức gói) và không đọc bộ đệm vượt quá số lượng mục đó.
Bài học kinh nghiệm:
Đừng coi sức mạnh tính toán hiện đại là điều hiển nhiên. Đã có lúc máy tính không hỗ trợ ethernet và khi xả một mảng có thể được coi là đắt tiền. Nếu bạn thực sự muốn xem chúng ta đã đi được bao xa, hãy tưởng tượng một hệ thống hầu như không có hình thức cấp phát bộ nhớ động. IE, quy trình điều hành phải phân bổ trước tất cả bộ nhớ cho tất cả các chương trình theo thứ tự và không có chương trình nào có thể phát triển vượt ra ngoài ranh giới đó. IE, phân bổ thêm bộ nhớ cho một chương trình mà không biên dịch lại toàn bộ hệ thống có thể gây ra sự cố lớn. Tôi tự hỏi nếu mọi người sẽ nói về những ngày thu gom rác trong cùng một ngày nào đó.
Khi thực hiện kết nối mạng với các giao thức tùy chỉnh (hoặc xử lý biểu diễn dữ liệu nhị phân nói chung), hãy đảm bảo bạn đọc thông số kỹ thuật cho đến khi bạn hiểu mọi chức năng của mọi giá trị được gửi qua đường ống. Ý tôi là, đọc nó cho đến khi mắt bạn đau. Mọi người xử lý dữ liệu bằng cách thao tác các bit hoặc byte riêng lẻ có cách làm rất thông minh và hiệu quả. Thiếu chi tiết nhỏ nhất có thể phá vỡ hệ thống.
Tổng thời gian để khắc phục là 2-3 ngày với phần lớn thời gian dành cho việc khác khi tôi cảm thấy thất vọng với điều này.
SideNote: Theo mặc định, máy tính chủ không hỗ trợ ethernet. Thẻ để lái nó đã được tùy chỉnh và trang bị thêm và ngăn xếp giao thức hầu như không tồn tại. Nhà phát triển mà tôi đang làm việc là một lập trình viên, anh ta không chỉ triển khai một phiên bản rút gọn của UDP và một ngăn xếp ethernet giả bắt chước (bộ xử lý không đủ mạnh để xử lý một ngăn xếp ethernet đầy đủ) trên hệ thống cho dự án này nhưng anh ấy đã làm nó trong vòng chưa đầy một tuần. Ông cũng là một trong những người lãnh đạo nhóm dự án ban đầu, người đã thiết kế và lập trình HĐH ngay từ đầu. Hãy nói, bất cứ điều gì anh ấy từng chia sẻ về máy tính / lập trình / kiến trúc cho dù tôi có mới bao lâu hay chưa, tôi đã lắng nghe từng từ.