Microsoft hesabıyla oturum açın
Oturum açın veya hesap oluşturun.
Merhaba,
Farklı bir hesap seçin.
Birden çok hesabınız var
Oturum açmak istediğiniz hesabı seçin.

Özet

Bazen, kişilerinize sesli bant dışı (OOB) verileri göndermeniz gerekir. Alıcılar, verileri alan tüm kullanıcılar veya uygulamalardır. Bu OOB verilerinin, gönderebilecek normal verilerden daha yüksek öncelikli veriler olarak işlenmesini istersiniz. Göndermek istediğiniz OOB verileri bir bayt ise, Select IŞLEVINI kullanarak OOB verilerini arayabilirsiniz. Verileri okumak için Al işlevini kullanabilirsiniz . Ancak, Transmission Control Protocol (TCP) ' da, OOB veri bloğu her zaman bir bayttır. Bu nedenle, çok baytlık OOB verileri gönderirseniz, yalnızca OOB verilerinin son baytı alınır. Geri kalan veriler normal veriler gibi değerlendirilir. Bu makalede, Microsoft Windows yuvası (Winsock) kullanarak birden çok baytlık OOB verilerini gönderme hakkında örnek kod kullanılmıştır.

BU GÖREVDE

GİRİŞ

Bu makalede, Winsock kullanarak birden çok bayt (karakter) bant dışı veri gönderme yöntemi açıklanır. Örnek uygulamalar Microsoft Visual C++ ' da oluşturulur. Bu OOB mekanizması Microsoft Windows yuva düzeyinde doğrudan desteklenmediğinden, bu OOB mekanizmasını uygulama düzeyinde uygulamalısınız. Bu doğru OOB verileri değildir. Bu örnek uygulamada, gönderen tarafı olarak da bilinen istemci tarafında, OOB verilerini ve normal verileri göndermek için iki yuva oluşturabilirsiniz. Alıcı tarafı olarak da bilinen sunucu tarafında, iki yuva kullanarak iki yuva kullanın. Bir iş parçacığı, OOB verileri içindir. Diğer iş parçacığı normal veriler içindir. OOB mekanizmasına benzetmek için bu iki yazışmayı eşitlemeniz gerekir. OOB verilerini işleyen iş parçacığının normal verileri işleyen iş parçacığından daha yüksek önceliğe sahip olduğundan emin olun.Not Bu örnek uygulama, çok baytlık OOB verilerini göndermenin bir yolunu açıklar. Kodu ortamınızda çalışması için kodu gözden geçirmeniz gerekebilir.başa dön

İstemci uygulaması oluşturma

  1. Bir istemci uygulaması oluşturun. Bu istemci uygulamasında aşağıdaki örnek kod, iki yuva oluşturmayı açıklar:

    SOCKET myOOBSocket = INVALID_SOCKET;SOCKET myNormalSocket = INVALID_SOCKET;myOOBSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);myNormalSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    Myoobsocket DEĞIŞKENI, OOB verilerini göndermek için kullanılır. Mynormalsocket değişkeni normal verileri göndermek için kullanılır.

  2. Myoobsocket değişkeninin gönderdiği VERILER doğru OOB verileri olmadığından, verileri göndermeye başlamadan önce, bu tür verilerin ne tür veriler için gönderildiğini bildirmeniz gerekir. Aşağıdaki örnek kod, sunucuya gönderilecek veri türünü bildirmek için başlangıç karakterinin nasıl gönderileceğini açıklar. OOB verileri için "U" kullanın ve normal veriler için "N" kullanın.

    int nErr, nSize;nErr = connect(myNormalSocket, (SOCKADDR *)&remoteIp, sizeof(remoteIp));//Look for a potential error here.//"remoteIp" is the remote address.nSize = send(myNormalSocket, "N",1, 0);//Look for a potential error here.nErr = connect(myOOBSocket, (SOCKADDR *)&remoteIp, sizeof(remoteIp));//Look for a potential error here.nSize = send(myOOBSocket,"U",1, 0);//Look for a potential error here.
  3. Aşağıdaki örnek kodda, istemci uygulamasının girişi kullanıcıdan nasıl izleneceği açıklanır. İstemci uygulaması, büyük harfli karakterleri OOB verileri olarak gönderir. Birden çok baytlık dize oluşturmak için her giriş karakterini yineleyin.

    for (;;) {int ch = _getch();_putch( ch );if (ch=='.') {shutdown(myOOBSocket, 2);        shutdown(myNormalSocket,2);break;}        char buf[10];        memset(buf, ch, sizeof(buf));        if (isupper(ch)) {nSize = send(myOOBSocket, buf, sizeof(buf), 0);//Do not use the MSG_OOB flag. Send it as normal data.} else {nSize = send(myNormalSocket, buf, sizeof(buf), 0);}...}

İstemci uygulaması için örnek kodu, MyClient. cppilebaşa dön

Sunucu uygulaması oluşturma

  1. Sunucu tarafında aşağıdaki örnek kod, iletişimde kullanılan bağlantı noktasını izlemek için bir dinleyici yuvasının nasıl oluşturulduğunu açıklar:

    int nErr;SOCKET myListener = INVALID_SOCKET;myListener = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//Look for a potential return error here.nErr = bind(myListener,(SOCKADDR *)&localIp,sizeof(localIp));//Look for a potential return error here.//"localIp" is the local address of the server.nErr = listen(myListener, 5);//Look for a potential return error here.
  2. Aşağıdaki örnek kod, dinleyici yuvasının gelen bağlantı deneme sayısını beklemesini sağlamak için Accept işlevinin nasıl çağralınacağını açıklar:

    for (;;) {struct sockaddr_in remoteIp;SOCKET remoteSocket = INVALID_SOCKET;int nAddrLen = sizeof(SOCKADDR);remoteSocket = accept(myListener, (SOCKADDR *)(&remoteIp), &nAddrLen);//"remoteIp" is a pointer to a buffer that receives //the address of the connecting entity.BYTE buffer[1+1];int recv_len=recv(remoteSocket,(char *)&buffer,1,0);//This supposes that the client sockets will send//"U" or "N" as the initial character.    buffer[recv_len] = '\0';if(strcmp((char *)buffer,"U")==0)hThread=CreateThread(0,0,OOBHandler,(LPVOID)remoteSocket, 0, &dwThreadId);//Create a new thread to process incoming OOB data. "OOBHandler" is a //pointer to the OOB data handler. else if(strcmp((char *)buffer,"N")==0)hThread=CreateThread(0,0,NormalHandler,(LPVOID)remoteSocket, 0, &dwThreadId);//Create a new thread to process incoming normal data. "NormalHandler" is //a pointer to the normal data handler....}
  3. OOB mekanizmasına benzetmek için bu iki yazışmayı eşitlemeniz gerekir. Bu örnek uygulamada, bunu yapmak için genel bir olay nesnesi kullanın. Dosyanın en üstüne aşağıdaki ifadeyi koyun.

    //Create a manual-reset event object. hRecvEvent=CreateEvent(NULL,TRUE,TRUE,"RecvEvent");
  4. Ayrı bir iş parçacığı tarafından yürütülen OOB işleyicisini oluşturun. Bu İşleyicide, veri ulaştığında algılamak için Select işlevini kullanırsınız. Veriler ulaştığında şu adımları izleyin:

    1. Hrecvevent olay nesnesini, sinyal dışı duruma ayarlamak Için ResetEvent işlevini çağırın.

      ResetEvent(hRecvEvent);

      Bu, başka bir iş parçacığında yürütülen normal veri işleyicisini engeller.

    2. Verileri okumak için RevC işlevini arayın.

      recv(remoteSocket,(char *)&buffer,sizeof(buffer) - 1,0);
    3. Arabelleğin tutabileceğinden daha fazla veri gönderilebileceğinden, tel için herhangi bir veri olup olmadığını belirlemek için, al işlevini MSG_PEEK bayrağıyla birlikte arayın.

      recv(remoteSocket,(char *)&buffer,sizeof(buffer)-1,MSG_PEEK);

      Okunması beklenen verilerin olup olmadığına bağlı olarak aşağıdaki yöntemlerden birini kullanın:

      • Okunması beklenmez veri yoksa, belirtilen olay nesnesini sinyal durumuna ayarlamak için SetEvent işlevini arayın.

        SetEvent(hRecvEvent);

        Bunu yaptığınızda, normal veri işleyicisi iş parçacığı devam edebilir. Normal veri işleyicisi iş parçacığı, normal veri işleyicisi iş parçacığından önce Hrecvevent olay nesnesini bekler.

      • Veriler hala okunması beklenmeye devam ediyorsa, kalan verileri okumak için alınan işlevi yeniden arayın. Ardından, bekleyen veriler için bir kez daha bakın.

    Tüm bekleyen veriler okuuncaya kadar adım 4-4c arasındaki adımları yineleyin.

  5. Normal veri işleyicisini oluşturun. Bu işleyici, normal veri işleyicisi verilerin geldiğini algıladığında normal veri işleyicisinin WaitForSingleObject işlevini çağırdığı durumlar dışında, OOB veri işleyicisine benzer.

    WaitForSingleObject(hRecvEvent,INFINITE);//You can set the interval parameter to a specific value if you do not want  //the normal data handler to wait for the OOB handler indefinitely when OOB data arrives continuously.

Sunucu uygulaması için örnek kodu, sunucum. cpp başa dön

İstemci uygulamasının MyClient. cpp örnek kodunu görüntüleme

Not Kod derlemek için, Ws2_32. lib Winsock kitaplık dosyasının başvurusunu eklemeniz gerekir.

#include <stdio.h>#include <stdlib.h>#include <conio.h>#include <assert.h>#include <winsock.h>main(int argc, char *argv[]){int nErr, nSize;WSADATA wsaData;SOCKET myOOBSocket = INVALID_SOCKET;SOCKET myNormalSocket = INVALID_SOCKET;unsigned short nPort; // Listen for the port number.struct sockaddr_in remoteIp;if (argc!=3){printf("TcpDemoC <RemoteIp> <Port>\n");return 0;}// The Init Socket API.nErr = WSAStartup(MAKEWORD(1,1),&wsaData);assert(nErr==0);nPort = (unsigned short)atol(argv[2]);myOOBSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);assert(myOOBSocket!=INVALID_SOCKET);myNormalSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);assert(myNormalSocket!=INVALID_SOCKET);// Connect to the remote address.remoteIp.sin_family = AF_INET;remoteIp.sin_port = htons(nPort);;remoteIp.sin_addr.S_un.S_addr = inet_addr(argv[1]);nErr = connect(myOOBSocket, (SOCKADDR *)&remoteIp, sizeof(remoteIp));if (nErr == SOCKET_ERROR) {printf("Connect failed because of %lX\n",  WSAGetLastError());goto Cleanup;}nSize = send(myOOBSocket,"U",1, 0);if (nSize == SOCKET_ERROR) {printf("Send failed because of %lX\n", WSAGetLastError());        goto Cleanup;}    nErr = connect(myNormalSocket, (SOCKADDR *)&remoteIp, sizeof(remoteIp));if (nErr == SOCKET_ERROR) {int error = WSAGetLastError();printf("Connect failed because of %lX\n", error);goto Cleanup;}    nSize = send(myNormalSocket, "N",1, 0);if (nSize == SOCKET_ERROR) {printf("Send failed because of %lX\n", WSAGetLastError());goto Cleanup;}printf("Read for input:\n");for (;;) {int ch = _getch();_putch( ch );if (ch=='.') {shutdown(myOOBSocket, 2);shutdown(myNormalSocket,2);break;}char buf[10];memset(buf, ch, sizeof(buf));if (isupper(ch)) {nSize = send(myOOBSocket, buf, sizeof(buf), 0);}else{nSize = send(myNormalSocket, buf, sizeof(buf), 0);}if (nSize == SOCKET_ERROR) {printf("Send failed because of %lX\n", WSAGetLastError());break;}}Sleep(1000);Cleanup:if (myOOBSocket!=INVALID_SOCKET)closesocket(myOOBSocket);if (myNormalSocket!=INVALID_SOCKET)closesocket(myNormalSocket);WSACleanup();return 0;}

başa dön

Sunucu uygulaması, sunucum. cpp için örnek kodu görüntüleme

Not Kod derlemek için, Ws2_32. lib Winsock kitaplık dosyasının başvurusunu eklemeniz gerekir.

#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <winsock.h>#include <assert.h>// Usage: myserver <port>HANDLE hRecvEvent; DWORD WINAPI OOBHandler(LPVOID lpParam){int nErr, nRecv_len;BYTE buffer[10 + 1];BOOL bClosing=FALSE;fd_set fdread;SOCKET remoteSocket=(SOCKET)lpParam;unsigned long ul=1;int nRet = ioctlsocket(remoteSocket, FIONBIO, &ul);if(SOCKET_ERROR==nRet){printf("Socket() failed: %d\n", WSAGetLastError());return 1;}printf("Waiting");for (int i=0; i<10; i++) {printf(".");Sleep(1000);}printf("The OOB handler is ready!\n");while (!bClosing){//Always clear the set before you call the select method.FD_ZERO(&fdread);//Add sockets to the sets.FD_SET(remoteSocket, &fdread);nErr=select(0,&fdread,0,0,0);if(nErr==SOCKET_ERROR){printf("Select() failed: %d\n",WSAGetLastError());return 1;}if(FD_ISSET(remoteSocket,&fdread)){ResetEvent(hRecvEvent);while(1){nRecv_len=recv(remoteSocket,(char *)&buffer,sizeof(buffer) - 1,0);                    if(nRecv_len==0){bClosing=TRUE;printf("The connection is closed!\n");break;}buffer[nRecv_len] = '\0';printf("[OOB]: %s\n", buffer);                    nRecv_len=recv(remoteSocket,(char *)&buffer,sizeof(buffer)-1,MSG_PEEK);if (nRecv_len==SOCKET_ERROR) {if(WSAGetLastError()==WSAEWOULDBLOCK)break;elseprintf("Recv() failed. Win32 error is 0x%lx\n", WSAGetLastError());}}SetEvent(hRecvEvent);} }return 0;}DWORD WINAPI NormalHandler(LPVOID lpParam){int nErr,nRecv_len;BYTE buffer[10 + 1];fd_set fdread;SOCKET remoteSocket=(SOCKET)lpParam;printf("Waiting");for (int i=0; i<10; i++) {        printf("*");Sleep(1000);}printf("Normal handler ready!\n");while(1) {//Always clear the set before you call the select method.FD_ZERO(&fdread);//Add sockets to the sets.FD_SET(remoteSocket, &fdread);nErr=select(0,&fdread,0,0,0);if(nErr==SOCKET_ERROR){printf("Select() failed: %d\n",WSAGetLastError());return 1;}if(FD_ISSET(remoteSocket,&fdread)){WaitForSingleObject(hRecvEvent,INFINITE);nRecv_len=recv(remoteSocket,(char *)&buffer,sizeof(buffer) - 1,0);            if (nRecv_len==SOCKET_ERROR) {printf("Recv() failed. Win32 error is 0x%lx\n", WSAGetLastError());return 1;}            if(nRecv_len==0){printf("Connection Closed!\n");break;}       buffer[nRecv_len] = '\0';printf("[Normal]: %s\n", buffer);}}return 0;}int main(int argc, char *argv[]){WSADATA wsaData;int nErr;SOCKET myListener = INVALID_SOCKET;struct sockaddr_in localIp;unsigned short nPort; DWORD dwThreadId;HANDLE hThread=NULL;if (argc!=2){printf("MyServer <Port>\n");return 0;}nPort = (unsigned short)atol(argv[1]);nErr = WSAStartup(MAKEWORD(2,0),&wsaData);assert(nErr==0);assert(wsaData.wVersion == MAKEWORD(2,0));myListener = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);assert(myListener!=INVALID_SOCKET);// Bind the listen socket to any local IP address.localIp.sin_family = AF_INET;localIp.sin_port = htons(nPort);;localIp.sin_addr.S_un.S_addr = INADDR_ANY;nErr = bind(myListener,(SOCKADDR *)&localIp,sizeof(localIp));assert(nErr!=SOCKET_ERROR);nErr = listen(myListener, 5);assert(nErr==0);//Create a manual-reset event object. hRecvEvent=CreateEvent(NULL,TRUE,TRUE,"RecvEvent");if (hRecvEvent == NULL) { printf("CreateEvent failed with error 0x%lx\n", GetLastError());return 1;}printf("The server is ready!\n");for (;;) {struct sockaddr_in remoteIp;SOCKET remoteSocket = INVALID_SOCKET;int nAddrLen = sizeof(SOCKADDR);remoteSocket = accept(myListener, (SOCKADDR *)(&remoteIp), &nAddrLen);if(remoteSocket == INVALID_SOCKET) {int error = WSAGetLastError();printf("Accept() failed. Win32 error is 0x%lx\n", GetLastError());goto Cleanup;} else {printf("Connected from %d.%d.%d.%d:%d\n", remoteIp.sin_addr.S_un.S_un_b.s_b1,remoteIp.sin_addr.S_un.S_un_b.s_b2,remoteIp.sin_addr.S_un.S_un_b.s_b3,remoteIp.sin_addr.S_un.S_un_b.s_b4,ntohs(remoteIp.sin_port));BYTE buffer[1+1];int nRecv_len=recv(remoteSocket,(char *)&buffer,1,0);if (nRecv_len==SOCKET_ERROR) {printf("Recv() failed. Win32 error is 0x%lx\n", WSAGetLastError());return 1;}    buffer[nRecv_len] = '\0';if(strcmp((char *)buffer,"U")==0)hThread=CreateThread(0,0,OOBHandler,(LPVOID)remoteSocket, 0, &dwThreadId);else if(strcmp((char *)buffer,"N")==0)hThread=CreateThread(0,0,NormalHandler,(LPVOID)remoteSocket, 0, &dwThreadId);           if(hThread==0){printf("CreateThread() failed: %d\n",GetLastError());return 1;}CloseHandle(hThread);}}closesocket(myListener);Cleanup:WSACleanup();return 0;}

başa dön

Örneği test etme

  1. Komut isteminde, sunucuyu bağlantı noktası 4444 ' na başlatmak için Sunucum. exe 4444 yazın. sunucu uygulaması aşağıdaki iletiyi görüntüler ve istemcileri bekler:

    Sunucu hazırdır!

  2. Farklı bir komut Istemi penceresinde, istemciyi başlatmak içinmyclient IPAddress 4444 yazın. Not Yer tutucu IPAddress , sunucunun IP adresi için bir yer tutucudur.

  3. Sunucu aşağıdakine benzer bir ileti görüntüler:

    Waiting.Waiting*..*Önceki iletiyi aldığınızda, sunucu devam etmeden önce 10 saniye içinde mesajlaşmayı yazmanız gerekir .

10 saniye sonra, sunucu aşağıdakileri görüntüler:

[OOB]: BBBBBBBBBB [OOB]: DDDDDDDDDD [OOB]: FFFFFFFFFF [OOB]: HHHHHHHHHH [normal]: aaaaaaaaaa [normal]: gggggggggg [normal]başa dön

Başvurular

Ek bilgi için, aşağıdaki Microsoft Developer Network (MSDN) Web sitelerini ziyaret edin:

Protokolden bağımsız bant dışı verilerhttp://msdn2.Microsoft.com/en-us/library/ms740102.aspxWinsock işlevlerihttp://msdn2.Microsoft.com/en-us/library/ms741394.aspxEk bilgi için, Microsoft Bilgi Bankası 'ndaki makaleyi görüntülemek üzere aşağıdaki makale numarasını tıklatın:

331756 Ioctlsocket işlevi, bant içi bant dışı verileri algılayamazbaşa dön

Daha fazla yardıma mı ihtiyacınız var?

Daha fazla seçenek mi istiyorsunuz?

Abonelik avantajlarını keşfedin, eğitim kurslarına göz atın, cihazınızın güvenliğini nasıl sağlayacağınızı öğrenin ve daha fazlasını yapın.

Topluluklar, soru sormanıza ve soruları yanıtlamanıza, geri bildirimde bulunmanıza ve zengin bilgiye sahip uzmanlardan bilgi almanıza yardımcı olur.

Bu bilgi yararlı oldu mu?

Dil kalitesinden ne kadar memnunsunuz?
Deneyiminizi ne etkiledi?
Gönder’e bastığınızda, geri bildiriminiz Microsoft ürün ve hizmetlerini geliştirmek için kullanılır. BT yöneticiniz bu verileri toplayabilecek. Gizlilik Bildirimi.

Geri bildiriminiz için teşekkürler!

×