Bagikan melalui


Fungsi WSAAccept (winsock2.h)

Fungsi WSAAccept secara kondisional menerima koneksi berdasarkan nilai pengembalian fungsi kondisi, memberikan kualitas spesifikasi alur layanan, dan memungkinkan transfer data koneksi.

Sintaks

SOCKET WSAAPI WSAAccept(
  [in]      SOCKET          s,
  [out]     sockaddr        *addr,
  [in, out] LPINT           addrlen,
  [in]      LPCONDITIONPROC lpfnCondition,
  [in]      DWORD_PTR       dwCallbackData
);

Parameter

[in] s

Deskriptor yang mengidentifikasi soket yang mendengarkan koneksi setelah panggilan ke fungsi dengar .

[out] addr

Penunjuk opsional ke struktur sockaddr yang menerima alamat entitas penghubung, seperti yang diketahui oleh lapisan komunikasi. Format parameter addr yang tepat ditentukan oleh keluarga alamat yang ditetapkan ketika soket dibuat.

[in, out] addrlen

Penunjuk opsional ke bilangan bulat yang berisi panjang struktur sockaddr yang diarahkan oleh parameter addr , dalam byte.

[in] lpfnCondition

Alamat fungsi kondisi opsional yang ditentukan aplikasi yang akan membuat keputusan terima/tolak berdasarkan informasi pemanggil yang diteruskan sebagai parameter, dan secara opsional membuat atau bergabung dengan grup soket dengan menetapkan nilai yang sesuai ke parameter hasil g fungsi ini. Jika parameter ini NULL, maka tidak ada fungsi kondisi yang dipanggil.

[in] dwCallbackData

Data panggilan balik diteruskan kembali ke fungsi kondisi yang ditentukan aplikasi sebagai nilai parameter dwCallbackData yang diteruskan ke fungsi kondisi. Parameter ini hanya berlaku jika parameter lpfnCondition bukan NULL. Parameter ini tidak ditafsirkan oleh Windows Sockets.

Mengembalikan nilai

Jika tidak ada kesalahan yang terjadi, WSAAccept mengembalikan nilai jenis SOCKET yang merupakan deskriptor untuk soket yang diterima. Jika tidak, nilai INVALID_SOCKET dikembalikan, dan kode kesalahan tertentu dapat diambil dengan memanggil WSAGetLastError.

Bilangan bulat yang disebut oleh addrlen awalnya berisi jumlah ruang yang diarahkan oleh addr. Saat dikembalikan, itu akan berisi panjang aktual dalam byte alamat yang dikembalikan.

Kode kesalahan Makna
WSAEACCES
Upaya dilakukan untuk mengakses soket dengan cara yang dilarang oleh izin aksesnya. Kesalahan ini dikembalikan jika permintaan koneksi yang ditawarkan telah kehabisan waktu atau ditarik.
WSAECONNREFUSED
Tidak ada koneksi yang dapat dibuat karena komputer target secara aktif menolaknya. Kesalahan ini dikembalikan jika permintaan koneksi ditolak secara paksa seperti yang ditunjukkan dalam nilai pengembalian fungsi kondisi (CF_REJECT).
WSAECONNRESET
Koneksi yang ada ditutup secara paksa oleh host jarak jauh. Kesalahan ini dikembalikan dari koneksi masuk ditunjukkan, tetapi kemudian dihentikan oleh peer jarak jauh sebelum menerima panggilan.
WSAEFAULT
Sistem mendeteksi alamat penunjuk yang tidak valid dalam mencoba menggunakan argumen penunjuk dalam panggilan. Kesalahan ini dikembalikan dari parameter addrlen terlalu kecil atau addr atau lpfnCondition bukan bagian dari ruang alamat pengguna.
WSAEINTR
Operasi pemblokiran terganggu oleh panggilan ke WSACancelBlockingCall. Kesalahan ini dikembalikan jika panggilan Windows Sockets 1.1 pemblokiran dibatalkan melalui WSACancelBlockingCall.
WSAEINPROGRESS
Operasi pemblokiran saat ini sedang dijalankan. Kesalahan ini dikembalikan jika pemblokiran panggilan Windows Sockets 1.1 sedang berlangsung.
WSAEINVAL
Argumen yang tidak valid disediakan. Kesalahan ini dikembalikan jika mendengarkan tidak dipanggil sebelum WSAAccept, nilai pengembalian fungsi kondisi bukan yang valid, atau kasus apa pun di mana soket yang ditentukan dalam keadaan tidak valid.
WSAEMFILE
Terlalu banyak soket terbuka. Kesalahan ini dikembalikan jika antrean tidak kosong saat masuk ke WSAAccept dan tidak ada deskriptor soket yang tersedia.
WSAENETDOWN
Operasi soket mengalami jaringan mati. Kesalahan ini dikembalikan jika subsistem jaringan gagal.
WSAENOBUFS
Operasi pada soket tidak dapat dilakukan karena sistem tidak memiliki ruang buffer yang cukup atau karena antrean penuh. Kesalahan ini dikembalikan jika tidak ada ruang buffer yang tersedia.
WSAENOTSOCK
Operasi dicoba pada sesuatu yang bukan soket. Kesalahan ini dikembalikan jika deskriptor soket yang diteruskan dalam parameter s bukan soket.
WSAEOPNOTSUPP
Keluarga protokol belum dikonfigurasi ke dalam sistem atau tidak ada implementasi untuk itu. Kesalahan ini dikembalikan jika soket yang direferensikan bukan jenis yang mendukung layanan berorientasi koneksi.
WSAEWOULDBLOCK
Operasi soket non-pemblokiran tidak dapat segera diselesaikan. Kesalahan ini dikembalikan jika soket ditandai sebagai tidak memblokir dan tidak ada koneksi yang akan diterima.
WSANOTINITIALISED
Aplikasi belum memanggil WSAStartup, atau WSAStartup gagal. Kesalahan ini dikembalikan dari panggilan yang berhasil ke dit fungsi WSAStartup tidak terjadi sebelum menggunakan fungsi ini.
WSATRY_AGAIN
Ini biasanya kesalahan sementara selama resolusi nama host dan berarti bahwa server lokal tidak menerima respons dari server otoritatif. Kesalahan ini dikembalikan jika penerimaan permintaan koneksi ditangguhkan seperti yang ditunjukkan dalam nilai pengembalian fungsi kondisi (CF_DEFER).

Keterangan

Fungsi WSAAccept mengekstrak koneksi pertama pada antrean koneksi yang tertunda pada soket , dan memeriksanya terhadap fungsi kondisi, asalkan fungsi kondisi ditentukan (yaitu, bukan NULL). Jika fungsi kondisi mengembalikan CF_ACCEPT, WSAAccept membuat soket baru. Soket yang baru dibuat memiliki properti yang sama dengan soket termasuk peristiwa asinkron yang terdaftar di WSAAsyncSelect atau dengan WSAEventSelect. Jika fungsi kondisi mengembalikan CF_REJECT, WSAAccept menolak permintaan koneksi. Fungsi kondisi berjalan dalam utas yang sama seperti fungsi ini, dan harus kembali sesegera mungkin. Jika keputusan tidak dapat segera dibuat, fungsi kondisi harus mengembalikan CF_DEFER untuk menunjukkan bahwa tidak ada keputusan yang dibuat, dan tidak ada tindakan tentang permintaan koneksi ini yang harus diambil oleh penyedia layanan. Ketika aplikasi siap untuk mengambil tindakan pada permintaan koneksi, aplikasi akan memanggil WSAAccept lagi dan mengembalikan CF_ACCEPT atau CF_REJECT sebagai nilai pengembalian dari fungsi kondisi.

Soket dalam mode default (pemblokiran) akan memblokir hingga koneksi ada ketika aplikasi memanggil WSAAccept dan tidak ada koneksi yang tertunda pada antrean.

Soket dalam mode nonblocking (pemblokiran) gagal dengan kesalahan WSAEWOULDBLOCK ketika aplikasi memanggil WSAAccept dan tidak ada koneksi yang tertunda pada antrean. Setelah WSAAccept berhasil dan mengembalikan handel soket baru, soket yang diterima tidak dapat digunakan untuk menerima koneksi lagi. Soket asli tetap terbuka dan mendengarkan permintaan koneksi baru.

Parameter addr adalah parameter hasil yang diisi dengan alamat entitas penghubung, seperti yang diketahui oleh lapisan komunikasi. Format parameter addr yang tepat ditentukan oleh keluarga alamat tempat komunikasi terjadi. Addrlen adalah parameter hasil nilai; awalnya harus berisi jumlah ruang yang ditujukkan oleh addr. Saat dikembalikan, itu akan berisi panjang aktual (dalam byte) dari alamat yang dikembalikan. Panggilan ini digunakan dengan jenis soket berorientasi koneksi seperti SOCK_STREAM. Jika addr dan/atau addrlen sama dengan NULL, maka tidak ada informasi tentang alamat jarak jauh soket yang diterima yang dikembalikan. Jika tidak, kedua parameter ini akan diisi jika koneksi berhasil diterima.

Prototipe fungsi kondisi didefinisikan dalam Winsock2.h file header sebagai LPCONDITIONPROC, sebagai berikut.

int CALLBACK 
ConditionFunc( 
  IN     LPWSABUF    lpCallerId, 
  IN     LPWSABUF    lpCallerData, 
  IN OUT LPQOS       lpSQOS, 
  IN OUT LPQOS       lpGQOS,
  IN     LPWSABUF    lpCalleeId, 
  IN     LPWSABUF    lpCalleeData, 
  OUT    GROUP FAR * g, 	
  IN     DWORD_PTR   dwCallbackData
);

ConditionFunc adalah tempat penampung untuk fungsi panggilan balik yang ditentukan aplikasi. Fungsi kondisi aktual harus berada di DLL atau modul aplikasi. Ini diekspor dalam file definisi modul.

Parameter lpCallerId menunjuk ke struktur WSABUF yang berisi alamat entitas penghubung, di mana parameter lensanya adalah panjang buffer dalam byte, dan parameter buf-nya adalah penunjuk ke buffer. lpCallerData adalah parameter nilai yang berisi data pengguna apa pun. Informasi dalam parameter ini dikirim bersama dengan permintaan koneksi. Jika tidak ada identifikasi penelepon atau data penelepon yang tersedia, parameter yang sesuai akan menjadi NULL. Banyak protokol jaringan tidak mendukung data pemanggil waktu sambung. Sebagian besar protokol jaringan konvensional dapat diharapkan untuk mendukung informasi pengidentifikasi pemanggil pada waktu permintaan koneksi. Bagian buf WSABUF yang diarahkan oleh lpCallerId menunjuk ke sockaddr. Struktur sockaddr ditafsirkan sesuai dengan keluarga alamatnya (biasanya dengan mentransmisikan sockaddr ke beberapa jenis khusus untuk keluarga alamat).

Parameter lpSQOS mereferensikan struktur FLOWSPEC untuk soket yang ditentukan oleh pemanggil, satu untuk setiap arah, diikuti oleh parameter khusus penyedia tambahan. Nilai spesifikasi alur pengiriman atau penerimaan akan diabaikan sebagaimana mestinya untuk soket satu arah. Nilai NULL menunjukkan bahwa tidak ada kualitas layanan yang disediakan penelepon dan bahwa tidak ada negosiasi yang dimungkinkan. Pointer lpSQOSnon-NULL menunjukkan bahwa kualitas negosiasi layanan akan terjadi atau bahwa penyedia siap untuk menerima kualitas permintaan layanan tanpa negosiasi.

Parameter lpGQOS dicadangkan, dan harus NULL. (dicadangkan untuk digunakan di masa mendatang dengan grup soket) mereferensikan struktur FLOWSPEC untuk grup soket yang akan dibuat pemanggil, satu untuk setiap arah, diikuti oleh parameter khusus penyedia tambahan. Nilai NULL untuk lpGQOS menunjukkan tidak ada kualitas layanan grup yang ditentukan penelepon. Kualitas informasi layanan dapat dikembalikan jika negosiasi terjadi.

lpCalleeId adalah parameter yang berisi alamat lokal entitas yang terhubung. Bagian buf dari WSABUF yang diarahkan oleh lpCalleeId menunjuk ke struktur sockaddr . Struktur sockaddr ditafsirkan sesuai dengan keluarga alamatnya (biasanya dengan mentransmisikan sockaddr ke beberapa jenis khusus untuk keluarga alamat seperti struct sockaddr_in).

lpCalleeData adalah parameter hasil yang digunakan oleh fungsi kondisi untuk menyediakan data pengguna kembali ke entitas penghubung. lpCalleeData-len> awalnya berisi panjang buffer yang dialokasikan oleh penyedia layanan dan ditunjukkan oleh lpCalleeData-buf>. Nilai nol berarti meneruskan data pengguna kembali ke pemanggil tidak didukung. Fungsi kondisi harus menyalin hingga lpCalleeData-len> byte data ke lpCalleeData-buf>, lalu memperbarui lpCalleeData-len> untuk menunjukkan jumlah byte aktual yang ditransfer. Jika tidak ada data pengguna yang akan diteruskan kembali ke pemanggil, fungsi kondisi harus mengatur lpCalleeData-len> ke nol. Format semua alamat dan data pengguna khusus untuk keluarga alamat tempat soket berada.

Parameter g ditetapkan dalam fungsi kondisi untuk menunjukkan salah satu tindakan berikut:

  • Jika g adalah pengidentifikasi grup soket yang ada, tambahkan s ke grup ini, asalkan semua persyaratan yang ditetapkan oleh grup ini terpenuhi.
  • Jika g = SG_UNCONSTRAINED_GROUP, buat grup soket yang tidak dibatasi dan miliki sebagai anggota pertama.
  • Jika g = SG_CONSTRAINED_GROUP, buat grup soket yang dibatasi dan miliki sebagai anggota pertama.
  • Jika g = nol, tidak ada operasi grup yang dilakukan.
Untuk grup yang tidak dibatasi, sekumpulan soket apa pun dapat dikelompokkan bersama selama didukung oleh satu penyedia layanan. Grup soket yang dibatasi hanya dapat terdiri dari soket berorientasi koneksi, dan mengharuskan koneksi pada semua soket yang dikelompokkan ke alamat yang sama pada host yang sama. Untuk grup soket yang baru dibuat, pengidentifikasi grup baru dapat diambil dengan menggunakan fungsi getsockopt dengan parameter tingkat yang diatur ke SOL_SOCKET dan parameter optname diatur ke SO_GROUP_ID. Grup soket dan ID grup soket terkait tetap valid hingga soket terakhir milik grup soket ini ditutup. ID grup soket unik di semua proses untuk penyedia layanan tertentu. Grup soket dan pengidentifikasi terkaitnya tetap valid hingga soket terakhir milik grup soket ini ditutup. Pengidentifikasi grup soket unik di semua proses untuk penyedia layanan tertentu. Untuk informasi selengkapnya tentang grup soket, lihat Keterangan untuk fungsi WSASocket .

Nilai parameter dwCallbackData yang diteruskan ke fungsi kondisi adalah nilai yang diteruskan sebagai parameter dwCallbackData dalam panggilan WSAAccept asli. Nilai ini hanya ditafsirkan oleh klien Windows Socket versi 2. Ini memungkinkan klien untuk meneruskan beberapa informasi konteks dari situs panggilan WSAAccept ke fungsi kondisi. Ini juga menyediakan fungsi kondisi dengan informasi tambahan yang diperlukan untuk menentukan apakah akan menerima koneksi atau tidak. Penggunaan umumnya adalah meneruskan penunjuk (pemeran yang cocok) ke struktur data yang berisi referensi ke objek yang ditentukan aplikasi yang terkait dengan soket ini.

Catatan Untuk melindungi penggunaan fungsi WSAAccept dari serangan SYN, aplikasi harus melakukan jabat tangan TCP penuh (SYN-SYNACK-ACK) sebelum melaporkan permintaan koneksi. Melindungi dari serangan SYN dengan cara ini menghasilkan opsi soket SO_CONDITIONAL_ACCEPT menjadi tidak operasi; fungsi kondisional masih dipanggil, dan fungsi WSAAccept beroperasi dengan benar, tetapi aplikasi server yang mengandalkan klien yang tidak dapat melakukan jabat tangan tidak akan beroperasi dengan benar.
 
Catatan Saat mengeluarkan panggilan Winsock pemblokiran seperti WSAAccept, Winsock mungkin perlu menunggu peristiwa jaringan sebelum panggilan dapat selesai. Winsock melakukan penantian yang dapat diperingatkan dalam situasi ini, yang dapat terganggu oleh panggilan prosedur asinkron (APC) yang dijadwalkan pada utas yang sama. Mengeluarkan panggilan Winsock pemblokiran lain di dalam APC yang mengganggu panggilan Winsock pemblokiran yang sedang berlangsung pada utas yang sama akan menyebabkan perilaku yang tidak terdefinisi, dan tidak boleh dicoba oleh klien Winsock.
 

Contoh Kode

Contoh berikut menunjukkan penggunaan fungsi WSAAccept .
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQOS pQos,
    LPQOS lpGQOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR * g,
    DWORD_PTR dwCallbackData
    )
{

    if (pQos != NULL) {
        RtlZeroMemory(pQos, sizeof(QOS));
        return CF_ACCEPT;
    } else
        return CF_REJECT;
}

int main() {

    /* Declare and initialize variables */
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    struct sockaddr_in saClient;
    int iClientSize = sizeof(saClient);
    u_short port = 27015;
    char* ip;
    sockaddr_in service;
    int error;

    /* Initialize Winsock */
    error = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (error) {
        printf("WSAStartup() failed with error: %d\n", error);
        return 1;
    }

    /* Create a TCP listening socket */
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {  
        printf("socket() failed with error: %d\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    /*-----------------------------------------  
     *  Set up the sock addr structure that the listening socket
     *  will be bound to. In this case, the structure holds the
     * local IP address and the port specified. */
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent* thisHost;
    thisHost = gethostbyname("");
    ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
    service.sin_addr.s_addr = inet_addr(ip);

    /*-----------------------------------------
     *  Bind the listening socket to the IP address.
     * and port number specified by the sockaddr structure. */
    error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
    if (error == SOCKET_ERROR) {  
        printf("bind() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
  
    /* Make the socket listen for incoming connection requests */
    error = listen(ListenSocket, 1);
    if (error == SOCKET_ERROR) {  
        printf("listen() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Listening...\n");
  
    /*-----------------------------------------
     *  Accept an incoming connection request on the
     *  listening socket and transfer control to the 
     * accepting socket. */
    AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize, 
        &ConditionAcceptFunc, NULL);
 
    /*  Now do some work with the AcceptSocket 
     *  At this point, the application could
     *  handle data transfer on the socket, or other socket
     * functionality.*/
    
    /* Then clean up and quit */

    closesocket(AcceptSocket);
    closesocket(ListenSocket);
    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

Persyaratan Nilai
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

WSAAsyncSelect

WSAConnect

WSASocket

Fungsi Winsock

Referensi Winsock

Menerima

Mengikat

sambungkan

getsockopt

Mendengarkan

pilih

sockaddr

soket