Windows Sockets: przykład gniazd korzystających z archiwów
W tym artykule przedstawiono przykład użycia klasy CSocket. Przykład wykorzystuje CArchive
obiekty do serializacji danych za pośrednictwem gniazda. Należy pamiętać, że nie jest to serializacja dokumentu do lub z pliku.
W poniższym przykładzie pokazano, jak używać archiwum do wysyłania i odbierania danych za pośrednictwem CSocket
obiektów. Przykład został zaprojektowany tak, aby dwa wystąpienia aplikacji (na tej samej maszynie lub na różnych maszynach w sieci) wymieniały dane. Jedno wystąpienie wysyła dane, które drugie wystąpienie odbiera i potwierdza. Każda aplikacja może zainicjować wymianę i może działać jako serwer lub jako klient z inną aplikacją. Następująca funkcja jest zdefiniowana w klasie widoków aplikacji:
void PacketSerialize(long nPackets, CArchive &arData, CArchive &arAck)
{
BYTE bValue = 0;
WORD nCopies = 0;
if (arData.IsStoring())
{
CString strText;
errno_t err;
unsigned int number;
for (int p = 0; p < nPackets; p++)
{
err = rand_s(&number);
// if (err == 0)...
bValue = (BYTE)(number % 256);
err = rand_s(&number);
// if (err == 0)...
nCopies = (WORD)(number % 32000);
// Send header information
arData << bValue << nCopies;
for (int c = 0; c < nCopies; c++)
{
// Send data
arData << bValue;
}
strText.Format(_T("Sender sent packet %d of %d (Value = %d, Copies = %d)"),
p + 1, nPackets, (int)bValue, nCopies);
// Send receipt string
arData << strText;
arData.Flush();
// Receive acknowledgment
arAck >> strText;
// display it
DisplayMessage(strText);
}
}
else
{
CString strText;
BYTE bCheck;
for (int p = 0; p < nPackets; p++)
{
// Receive header information
arData >> bCheck >> nCopies;
for (int c = 0; c < nCopies; c++)
{
// Receive data
arData >> bValue;
if (bCheck != bValue)
{
AfxMessageBox(_T("Packet Failure"));
}
}
// Receive receipt string and display it
arData >> strText;
DisplayMessage(strText);
strText.Format(_T("Recipient received packet %d of %d (Value = %d, Copies = %d)"),
p + 1, nPackets, (int)bValue, nCopies);
// Send acknowledgment
arAck << strText;
arAck.Flush();
}
}
}
Najważniejszą rzeczą w tym przykładzie jest to, że jego struktura jest równoległa względem funkcji MFC Serialize
. Funkcja PacketSerialize
składowa składa się z instrukcji if
z klauzulą else
. Funkcja odbiera dwa odwołania CArchive jako parametry: arData i arAck. Jeśli obiekt archiwum arData jest ustawiony na przechowywanie (wysyłanie), if
gałąź jest wykonywana; w przeciwnym razie jeśli arData jest ustawiona na ładowanie (odbieranie), funkcja przyjmuje else
gałąź. Aby uzyskać więcej informacji na temat serializacji w MFC, zobacz Serializacja.
Uwaga
Zakłada się, że obiekt arAck archive jest przeciwieństwem arData. Jeśli arData jest do wysyłania, arAck odbiera, a odwrotnie ma wartość true.
W przypadku wysyłania przykładowa funkcja wykonuje pętle dla określonej liczby razy, za każdym razem generując dane losowe do celów demonstracyjnych. Aplikacja uzyska rzeczywiste dane z jakiegoś źródła, takiego jak plik. Operator wstawiania archiwum arData (<<) służy do wysyłania strumienia trzech kolejnych fragmentów danych:
"nagłówek", który określa charakter danych (w tym przypadku wartość zmiennej bValue i liczbę kopii, które zostaną wysłane).
Oba elementy są generowane losowo w tym przykładzie.
Określona liczba kopii danych.
Pętla wewnętrzna
for
wysyła wartość bValue określoną liczbę razy.Ciąg o nazwie strText wyświetlany użytkownikowi przez odbiorcę.
W przypadku odbierania funkcja działa podobnie, z tą różnicą, że używa operatora wyodrębniania archiwum (>>), aby pobrać dane z archiwum. Aplikacja odbierającą weryfikuje odbierane dane, wyświetla końcowy komunikat "Odebrano", a następnie wysyła z powrotem komunikat "Wysłane" dla aplikacji wysyłającej do wyświetlenia.
W tym modelu komunikacji słowo "Odebrano", komunikat wysłany w zmiennej strText , jest wyświetlany na drugim końcu komunikacji, dlatego określa użytkownikowi odbierającemu, że odebrano pewną liczbę pakietów danych. Odbiorca odpowiada za pomocą podobnego ciągu z napisem "Sent", aby wyświetlić go na ekranie oryginalnego nadawcy. Potwierdzenie obu ciągów wskazuje, że nastąpiła pomyślna komunikacja.
Uwaga
Jeśli piszesz program kliencki MFC do komunikowania się z ustalonymi serwerami (innych niż MFC), nie wysyłaj obiektów języka C++ za pośrednictwem archiwum. Jeśli serwer nie jest aplikacją MFC, która rozumie rodzaje obiektów, które chcesz wysłać, nie będzie mogła odbierać i deserializować obiektów. Przykład w artykule Windows Sockets: Byte Ordering pokazuje komunikację tego typu.
Aby uzyskać więcej informacji, zobacz Windows Sockets Specification: htonl, htons, ntohl, ntohs. Aby uzyskać więcej informacji, zobacz:
Zobacz też
Gniazda systemu Windows w MFC
CArchive::IsStoring
CArchive::, operator <<
CArchive::, operator >>
CArchive::Flush
CObject::Serialize