Bagikan melalui


Fungsi WSAWaitForMultipleEvents (winsock2.h)

Fungsi WSAWaitForMultipleEvents kembali ketika satu atau semua objek peristiwa yang ditentukan berada dalam status tersinyal, ketika interval waktu habis berakhir, atau ketika rutinitas penyelesaian I/O telah dijalankan.

Sintaks

DWORD WSAAPI WSAWaitForMultipleEvents(
  [in] DWORD          cEvents,
  [in] const WSAEVENT *lphEvents,
  [in] BOOL           fWaitAll,
  [in] DWORD          dwTimeout,
  [in] BOOL           fAlertable
);

Parameter

[in] cEvents

Jumlah handel objek peristiwa dalam array yang ditunjukkan oleh lphEvents. Jumlah maksimum penanganan objek peristiwa adalah WSA_MAXIMUM_WAIT_EVENTS. Satu atau beberapa peristiwa harus ditentukan.

[in] lphEvents

Penunjuk ke array handel objek peristiwa. Array dapat berisi handel objek dari berbagai jenis. Ini mungkin tidak berisi beberapa salinan handel yang sama jika parameter fWaitAll diatur ke TRUE. Jika salah satu handel ini ditutup saat penantian masih tertunda, perilaku WSAWaitForMultipleEvents tidak terdefinisi.

Handel harus memiliki hak akses SYNCHRONIZE . Untuk informasi selengkapnya, lihat Hak Akses Standar.

[in] fWaitAll

Nilai yang menentukan jenis tunggu. Jika TRUE, fungsi akan kembali saat status semua objek dalam array lphEvents diberi sinyal. Jika FALSE, fungsi akan kembali saat salah satu objek peristiwa diberi sinyal. Dalam kasus terakhir, nilai pengembalian dikurangi WSA_WAIT_EVENT_0 menunjukkan indeks objek peristiwa yang statusnya menyebabkan fungsi dikembalikan. Jika lebih dari satu objek peristiwa menjadi sinyal selama panggilan, ini adalah indeks array ke objek peristiwa yang disinyalir dengan nilai indeks terkecil dari semua objek peristiwa yang disinyalir.

[in] dwTimeout

Interval waktu habis, dalam milidetik. WSAWaitForMultipleEvents mengembalikan jika interval waktu habis kedaluwarsa, bahkan jika kondisi yang ditentukan oleh parameter fWaitAll tidak terpenuhi. Jika parameter dwTimeout adalah nol, WSAWaitForMultipleEvents menguji status objek peristiwa yang ditentukan dan segera kembali. Jika dwTimeoutWSA_INFINITE, WSAWaitForMultipleEvents menunggu selamanya; artinya, interval waktu habis tidak pernah kedaluwarsa.

[in] fAlertable

Nilai yang menentukan apakah utas ditempatkan dalam status tunggu yang dapat diperingatkan sehingga sistem dapat menjalankan rutinitas penyelesaian I/O. Jika TRUE, utas ditempatkan dalam status tunggu yang dapat diperingatkan dan WSAWaitForMultipleEvents dapat kembali ketika sistem menjalankan rutinitas penyelesaian I/O. Dalam hal ini, WSA_WAIT_IO_COMPLETION dikembalikan dan peristiwa yang sedang ditunggu belum disinyalir. Aplikasi harus memanggil fungsi WSAWaitForMultipleEvents lagi. Jika FALSE, utas tidak ditempatkan dalam status tunggu yang dapat diperingatkan dan rutinitas penyelesaian I/O tidak dijalankan.

Mengembalikan nilai

Jika fungsi WSAWaitForMultipleEvents berhasil, nilai pengembalian setelah berhasil adalah salah satu nilai berikut.

Tampilkan Nilai Makna
WSA_WAIT_EVENT_0 ke (WSA_WAIT_EVENT_0 + cEvents - 1)
Jika parameter fWaitAllTRUE, nilai pengembalian menunjukkan bahwa semua objek peristiwa yang ditentukan diberi sinyal.

Jika parameter fWaitAllFALSE, nilai yang dikembalikan dikurangi WSA_WAIT_EVENT_0 menunjukkan indeks array lphEvents dari objek peristiwa bersinyali yang memenuhi penantian. Jika lebih dari satu objek peristiwa menjadi sinyal selama panggilan, nilai pengembalian menunjukkan indeks array lphEvents dari objek peristiwa yang disinyalir dengan nilai indeks terkecil dari semua objek peristiwa yang disinyalir.

WSA_WAIT_IO_COMPLETION
Penantian berakhir dengan satu atau beberapa rutinitas penyelesaian I/O yang dijalankan. Peristiwa yang sedang ditunggu-tunggu belum disinyalir. Aplikasi harus memanggil fungsi WSAWaitForMultipleEvents lagi. Nilai yang dikembalikan ini hanya dapat dikembalikan jika parameter fAlertable adalah TRUE.
WSA_WAIT_TIMEOUT
Interval waktu habis berlalu dan kondisi yang ditentukan oleh parameter fWaitAll tidak terpenuhi. Tidak ada rutinitas penyelesaian I/O yang dijalankan.
 

Jika fungsi WSAWaitForMultipleEvents gagal, nilai yang dikembalikan WSA_WAIT_FAILED. Tabel berikut ini mencantumkan nilai yang bisa digunakan dengan WSAGetLastError untuk mendapatkan informasi kesalahan yang diperluas.

Kode kesalahan Makna
WSANOTINITIALISED Panggilan WSAStartup yang berhasil harus terjadi sebelum menggunakan fungsi ini.
WSAENETDOWN Subsistem jaringan gagal.
WSAEINPROGRESS Pemblokiran panggilan Windows Sockets 1.1 sedang berlangsung, atau penyedia layanan masih memproses fungsi panggilan balik.
WSA_NOT_ENOUGH_MEMORY Memori bebas tidak cukup tersedia untuk menyelesaikan operasi.
WSA_INVALID_HANDLE Satu atau beberapa nilai dalam array lphEvents bukan handel objek peristiwa yang valid.
WSA_INVALID_PARAMETER Parameter cEvents tidak berisi jumlah handel yang valid.

Keterangan

Fungsi WSAWaitForMultipleEvents menentukan apakah kriteria tunggu telah terpenuhi. Jika kriteria belum terpenuhi, utas panggilan memasuki status tunggu. Ini tidak menggunakan waktu prosesor sambil menunggu kriteria terpenuhi.

Fungsi WSAWaitForMultipleEvents kembali ketika salah satu atau semua objek yang ditentukan berada dalam status disinyalir, atau ketika interval waktu habis berlalu.

Ketika parameter bWaitAllTRUE, operasi tunggu selesai hanya ketika status semua objek telah diatur ke sinyal. Fungsi tidak mengubah status objek yang ditentukan sampai status semua objek telah diatur ke sinyal.

Ketika parameter bWaitAllFALSE, WSAWaitForMultipleEvents memeriksa handel dalam array lphEvents agar dimulai dengan indeks 0, hingga salah satu objek diberi sinyal. Jika beberapa objek menjadi sinyal, fungsi mengembalikan indeks handel pertama dalam array lphEvents yang objeknya diberi sinyal.

Fungsi ini juga digunakan untuk melakukan tunggu yang dapat diperingatkan dengan mengatur parameter fAlertable ke TRUE. Ini memungkinkan fungsi untuk kembali ketika sistem menjalankan rutinitas penyelesaian I/O oleh utas panggilan.

Utas harus dalam status tunggu yang dapat diperingatkan agar sistem menjalankan rutinitas penyelesaian I/O (panggilan prosedur asinkron atau APC). Jadi jika aplikasi memanggil WSAWaitForMultipleEvents ketika ada operasi asinkron yang tertunda yang memiliki rutinitas penyelesaian I/O dan parameter fAlertableadalah FALSE, maka rutinitas penyelesaian I/O tersebut tidak akan dijalankan meskipun operasi I/O tersebut selesai.

Jika parameter fAlertableTRUE dan salah satu operasi yang tertunda selesai, APC dijalankan dan WSAWaitForMultipleEvents akan mengembalikan WSA_IO_COMPLETION. Peristiwa yang tertunda belum disinyalir. Aplikasi harus memanggil fungsi WSAWaitForMultipleEvents lagi.

Aplikasi yang memerlukan status tunggu yang dapat diperingatkan tanpa menunggu objek peristiwa apa pun disinyalir harus menggunakan fungsi Windows SleepEx .

Implementasi WSAWaitForMultipleEvents saat ini memanggil fungsi WaitForMultipleObjectsEx .

Catatan Berhati-hatilah saat memanggil WSAWaitForMultipleEvents dengan kode yang secara langsung atau tidak langsung membuat jendela. Jika utas membuat jendela apa pun, utas harus memproses pesan. Siaran pesan dikirim ke semua jendela dalam sistem. Utas yang menggunakan WSAWaitForMultipleEvents tanpa batas waktu habis (parameter dwTimeout yang diatur ke WSA_INFINITE) dapat menyebabkan sistem mengalami kebuntuan.
 

Contoh Kode

Contoh kode berikut menunjukkan cara menggunakan fungsi WSAWaitForMultipleEvents .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DATA_BUFSIZE 4096

int main()
{
    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData = { 0 };
    int iResult = 0;
    BOOL bResult = TRUE;

    WSABUF DataBuf;
    char buffer[DATA_BUFSIZE];

    DWORD EventTotal = 0;
    DWORD RecvBytes = 0;
    DWORD Flags = 0;
    DWORD BytesTransferred = 0;

    WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
    WSAOVERLAPPED AcceptOverlapped;
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;

    DWORD Index;

    //-----------------------------------------
    // Initialize Winsock
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }
    //-----------------------------------------
    // Create a listening socket bound to a local
    // IP address and the port specified
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error = %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    u_short port = 27015;
    char *ip;
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent *thisHost;

    thisHost = gethostbyname("");
    if (thisHost == NULL) {
        wprintf(L"gethostbyname failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ip = inet_ntoa(*(struct in_addr *) *thisHost->h_addr_list);

    service.sin_addr.s_addr = inet_addr(ip);

    //-----------------------------------------
    // Bind the listening socket to the local IP address
    // and port number
    iResult = bind(ListenSocket, (SOCKADDR *) & service, sizeof (SOCKADDR));
    if (iResult != 0) {
        wprintf(L"bind failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //-----------------------------------------
    // Set the socket to listen for incoming
    // connection requests
    iResult = listen(ListenSocket, 1);
    if (iResult != 0) {
        wprintf(L"listen failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Listening...\n");

    //-----------------------------------------
    // Accept and incoming connection request
    AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Client Accepted...\n");

    //-----------------------------------------
    // Create an event handle and setup an overlapped structure.
    EventArray[EventTotal] = WSACreateEvent();
    if (EventArray[EventTotal] == WSA_INVALID_EVENT) {
        wprintf(L"WSACreateEvent failed with error = %d\n", WSAGetLastError());
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));
    AcceptOverlapped.hEvent = EventArray[EventTotal];

    DataBuf.len = DATA_BUFSIZE;
    DataBuf.buf = buffer;

    EventTotal++;

    //-----------------------------------------
    // Call WSARecv to receive data into DataBuf on 
    // the accepted socket in overlapped I/O mode
    if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) ==
        SOCKET_ERROR) {
        iResult = WSAGetLastError();
        if (iResult != WSA_IO_PENDING)
            wprintf(L"WSARecv failed with error = %d\n", iResult);
    }
    //-----------------------------------------
    // Process overlapped receives on the socket
    while (1) {

        //-----------------------------------------
        // Wait for the overlapped I/O call to complete
        Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);

        //-----------------------------------------
        // Reset the signaled event
        bResult = WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
        if (bResult == FALSE) {
            wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // Determine the status of the overlapped event
        bResult =
            WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE,
                                   &Flags);
        if (bResult == FALSE) {
            wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // If the connection has been closed, close the accepted socket
        if (BytesTransferred == 0) {
            wprintf(L"Closing accept Socket %d\n", AcceptSocket);
            closesocket(ListenSocket);
            closesocket(AcceptSocket);
            WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
            WSACleanup();
            return 1;
        }
        //-----------------------------------------
        // If data has been received, echo the received data
        // from DataBuf back to the client
        iResult =
            WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL);
        if (iResult != 0) {
            wprintf(L"WSASend failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------         
        // Reset the changed flags and overlapped structure
        Flags = 0;
        ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));

        AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

        //-----------------------------------------
        // Reset the data buffer
        DataBuf.len = DATA_BUFSIZE;
        DataBuf.buf = buffer;
    }

    closesocket(ListenSocket);
    closesocket(AcceptSocket);
    WSACleanup();

    return 0;
}


Windows Phone 8: Fungsi ini didukung untuk aplikasi Windows Phone Store di Windows Phone 8 dan yang lebih baru.

Windows 8.1 dan Windows Server 2012 R2: Fungsi ini didukung untuk aplikasi Windows Store di Windows 8.1, Windows Server 2012 R2, dan yang lebih baru.

Persyaratan

   
Klien minimum yang didukung Windows 8.1, Windows Vista [aplikasi desktop | Aplikasi UWP]
Server minimum yang didukung Windows Server 2003 [aplikasi desktop | Aplikasi UWP]
Target Platform Windows
Header winsock2.h
Pustaka Ws2_32.lib
DLL Ws2_32.dll

Lihat juga

Hak Akses Standar

WSACloseEvent

WSACreateEvent

WaitForMultipleObjectsEx

Fungsi Winsock

Referensi Winsock