Fungsi WSARecvFrom (winsock2.h)
Fungsi WSARecvFrom menerima datagram dan menyimpan alamat sumber.
Sintaks
int WSAAPI WSARecvFrom(
[in] SOCKET s,
[in, out] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesRecvd,
[in, out] LPDWORD lpFlags,
[out] sockaddr *lpFrom,
[in, out] LPINT lpFromlen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameter
[in] s
Deskriptor yang mengidentifikasi soket.
[in, out] lpBuffers
Penunjuk ke array struktur WSABUF . Setiap struktur WSABUF berisi pointer ke buffer dan panjang buffer.
[in] dwBufferCount
Jumlah struktur WSABUF dalam array lpBuffers .
[out] lpNumberOfBytesRecvd
Penunjuk ke jumlah byte yang diterima oleh panggilan ini jika operasi WSARecvFrom segera selesai.
Gunakan NULL untuk parameter ini jika parameter lpOverlapped bukan NULL untuk menghindari hasil yang berpotensi salah. Parameter ini dapat berupa NULL hanya jika parameter lpOverlapped bukan NULL.
[in, out] lpFlags
Pointer ke bendera yang digunakan untuk memodifikasi perilaku panggilan fungsi WSARecvFrom . Lihat keterangan di bawah ini.
[out] lpFrom
Penunjuk opsional ke buffer yang akan menyimpan alamat sumber setelah menyelesaikan operasi yang tumpang tindih.
[in, out] lpFromlen
Penunjuk ke ukuran, dalam byte, dari buffer "dari" yang diperlukan hanya jika lpFrom ditentukan.
[in] lpOverlapped
Penunjuk ke struktur WSAOVERLAPPED (diabaikan untuk soket yang tidak tumpang tindih).
[in] lpCompletionRoutine
Jenis: LPWSAOVERLAPPED_COMPLETION_ROUTINE _In_opt_
Penunjuk ke rutinitas penyelesaian yang dipanggil ketika operasi WSARecvFrom telah selesai (diabaikan untuk soket yang tidak tumpang tindih).
Nilai kembali
Jika tidak ada kesalahan yang terjadi dan operasi terima telah segera selesai, WSARecvFrom mengembalikan nol. Dalam hal ini, rutinitas penyelesaian telah dijadwalkan untuk dipanggil setelah utas panggilan berada dalam status yang dapat diperingatkan. Jika tidak, nilai SOCKET_ERROR dikembalikan, dan kode kesalahan tertentu dapat diambil dengan memanggil WSAGetLastError. Kode kesalahan WSA_IO_PENDING menunjukkan bahwa operasi yang tumpang tindih telah berhasil dimulai dan penyelesaian tersebut akan ditunjukkan di lain waktu. Kode kesalahan lainnya menunjukkan bahwa operasi yang tumpang tindih tidak berhasil dimulai dan tidak ada indikasi penyelesaian yang akan terjadi.
Kode kesalahan | Makna |
---|---|
Sirkuit virtual direset oleh sisi jarak jauh yang mengeksekusi penutupan yang keras atau abortif. Aplikasi harus menutup soket karena tidak lagi dapat digunakan. Untuk soket datagram UPD, kesalahan ini akan menunjukkan bahwa operasi pengiriman sebelumnya menghasilkan pesan "Port Tidak Dapat Dijangkau" ICMP. | |
Parameter lpBuffers, lpFlags, lpFrom, lpNumberOfBytesRecvd, lpFromlen, lpOverlapped, atau lpCompletionRoutine tidak sepenuhnya terkandung dalam bagian ruang alamat pengguna yang valid: buffer lpFrom terlalu kecil untuk mengakomodasi alamat serekan. | |
Panggilan Windows Sockets 1.1 yang diblokir sedang berlangsung, atau penyedia layanan masih memproses fungsi panggilan balik. | |
Panggilan Windows Socket 1.1 pemblokiran dibatalkan melalui WSACancelBlockingCall. | |
Soket belum terikat (dengan ikatan, misalnya). | |
Pesan terlalu besar untuk buffer yang ditentukan dan (hanya untuk protokol yang tidak dapat diandalkan) bagian pesan berikutnya yang tidak masuk ke dalam buffer telah dibuang. | |
Subsistem jaringan gagal. | |
Untuk soket datagram, kesalahan ini menunjukkan bahwa waktu hidup telah kedaluwarsa. | |
Soket tidak tersambung (hanya soket berorientasi koneksi). | |
Windows NT:
Soket yang tumpang tindih: Ada terlalu banyak permintaan I/O yang tumpang tindih. Soket yang tidak tumpang tindih: Soket ditandai sebagai nonblocking dan operasi terima tidak dapat segera diselesaikan. |
|
Panggilan WSAStartup yang berhasil harus terjadi sebelum menggunakan fungsi ini. | |
Operasi tumpang tindih berhasil dimulai dan penyelesaian akan ditunjukkan nanti. | |
Operasi yang tumpang tindih telah dibatalkan karena penutupan soket. |
Keterangan
Fungsi WSARecvFrom menyediakan fungsionalitas di atas dan di atas fungsi recvfrom standar di tiga area penting:
- Ini dapat digunakan bersama dengan soket yang tumpang tindih untuk melakukan operasi penerimaan yang tumpang tindih.
- Ini memungkinkan beberapa buffer penerima untuk ditentukan sehingga berlaku untuk jenis I/O yang tersebar/kumpulkan.
- Parameter lpFlags adalah parameter input dan output, memungkinkan aplikasi merasakan status output dari bit bendera MSG_PARTIAL . Ketahuilah bahwa bit bendera MSG_PARTIAL tidak didukung oleh semua protokol.
Untuk soket yang tumpang tindih, fungsi ini digunakan untuk memposting satu atau beberapa buffer di mana data masuk akan ditempatkan saat tersedia pada soket (mungkin terhubung), setelah itu indikasi penyelesaian yang ditentukan aplikasi (pemanggilan rutinitas penyelesaian atau pengaturan objek peristiwa) terjadi. Jika operasi tidak segera selesai, status penyelesaian akhir diambil melalui rutinitas penyelesaian atau WSAGetOverlappedResult. Selain itu, nilai yang ditunjukkan oleh lpFrom dan lpFromlen tidak diperbarui sampai penyelesaian itu sendiri ditunjukkan. Aplikasi tidak boleh menggunakan atau mengganggu nilai-nilai ini sampai telah diperbarui; oleh karena itu aplikasi tidak boleh menggunakan variabel otomatis (yaitu, berbasis tumpukan) untuk parameter ini.
Untuk soket yang tidak tumpang tindih, semantik pemblokiran identik dengan fungsi WSARecv standar dan parameter lpOverlapped dan lpCompletionRoutine diabaikan. Data apa pun yang telah diterima dan di-buffer oleh transportasi akan disalin ke dalam buffer pengguna. Untuk kasus soket pemblokiran tanpa data yang saat ini telah diterima dan di-buffer oleh transportasi, panggilan akan memblokir hingga data diterima.
Buffer diisi dalam urutan di mana buffer muncul dalam array yang ditunjukkan oleh lpBuffers, dan buffer dikemas sehingga tidak ada lubang yang dibuat.
Jika fungsi ini selesai dengan cara yang tumpang tindih, penyedia layanan Winsock bertanggung jawab untuk menangkap struktur WSABUF sebelum kembali dari panggilan ini. Ini memungkinkan aplikasi untuk membangun array WSABUF berbasis tumpukan yang diacu oleh parameter lpBuffers .
Untuk jenis soket tanpa koneksi, alamat asal data disalin ke buffer yang ditunjukkan oleh lpFrom. Nilai yang ditunjukkan oleh lpFromlen diinisialisasi ke ukuran buffer ini, dan dimodifikasi pada penyelesaian untuk menunjukkan ukuran sebenarnya dari alamat yang disimpan di sana. Seperti yang dinyatakan sebelumnya untuk soket yang tumpang tindih, parameter lpFrom dan lpFromlen tidak diperbarui sampai setelah I/O yang tumpang tindih selesai. Memori yang ditujukan oleh parameter ini harus, oleh karena itu, tetap tersedia untuk penyedia layanan dan tidak dapat dialokasikan pada bingkai tumpukan aplikasi. Parameter lpFrom dan lpFromlen diabaikan untuk soket berorientasi koneksi.
Untuk soket gaya aliran byte (misalnya, ketik SOCK_STREAM), data masuk ditempatkan ke dalam buffer hingga:
- Buffer diisi.
- Sambungan ditutup.
- Data yang di-buffer secara internal habis.
Parameter lpFlags dapat digunakan untuk memengaruhi perilaku pemanggilan fungsi di luar opsi yang ditentukan untuk soket terkait. Artinya, semantik fungsi ini ditentukan oleh opsi soket dan parameter lpFlags . Yang terakhir dibangun dengan menggunakan operator OR bitwise dengan salah satu nilai yang tercantum dalam tabel berikut.
Nilai | Makna |
---|---|
MSG_PEEK | Mempratinjau data masuk. Data disalin ke dalam buffer, tetapi tidak dihapus dari antrean input. Bendera ini hanya berlaku untuk soket yang tidak tumpang tindih. |
MSG_OOB | Memproses data OOB. |
MSG_PARTIAL | Bendera ini hanya untuk soket berorientasi pesan. Pada output, bendera ini menunjukkan bahwa data adalah bagian dari pesan yang dikirimkan oleh pengirim. Bagian pesan yang tersisa akan dikirimkan dalam operasi penerimaan berikutnya. Operasi terima berikutnya dengan bendera MSG_PARTIAL dihapus menunjukkan akhir pesan pengirim.
Sebagai parameter input, bendera ini menunjukkan bahwa operasi penerimaan harus selesai meskipun hanya sebagian pesan yang telah diterima oleh penyedia layanan. |
Untuk soket berorientasi pesan, bit MSG_PARTIAL diatur dalam parameter lpFlags jika pesan parsial diterima. Jika pesan lengkap diterima, MSG_PARTIALdibersihkan di lpFlags. Dalam kasus penyelesaian tertunda, nilai yang ditunjukkan oleh lpFlags tidak diperbarui. Ketika penyelesaian telah ditunjukkan, aplikasi harus memanggil WSAGetOverlappedResult dan memeriksa bendera yang ditunjukkan oleh parameter lpdwFlags .
I/O Soket Tumpang Tindih
Jika operasi yang tumpang tindih segera selesai, WSARecvFrom mengembalikan nilai nol dan parameter lpNumberOfBytesRecvd diperbarui dengan jumlah byte yang diterima dan bit bendera yang ditunjukkan oleh parameter lpFlags juga diperbarui. Jika operasi yang tumpang tindih berhasil dimulai dan akan selesai nanti, WSARecvFrom mengembalikan SOCKET_ERROR dan menunjukkan kode kesalahan WSA_IO_PENDING. Dalam hal ini, lpNumberOfBytesRecvd dan lpFlags tidak diperbarui. Ketika operasi yang tumpang tindih menyelesaikan jumlah data yang ditransfer ditunjukkan baik melalui parameter cbTransferred dalam rutinitas penyelesaian (jika ditentukan), atau melalui parameter lpcbTransfer di WSAGetOverlappedResult. Nilai bendera diperoleh baik melalui parameter dwFlags dari rutinitas penyelesaian, atau dengan memeriksa parameter lpdwFlagsWSAGetOverlappedResult.Fungsi WSARecvFrom dapat dipanggil dari dalam rutinitas penyelesaian fungsi WSARecv, WSARecvFrom, WSASend, atau WSASendTo sebelumnya. Untuk soket tertentu, rutinitas penyelesaian I/O tidak akan ditumpuk. Ini memungkinkan transmisi data sensitif waktu terjadi sepenuhnya dalam konteks preemptive.
Parameter lpOverlapped harus valid selama durasi operasi yang tumpang tindih. Jika beberapa operasi I/O secara bersamaan luar biasa, masing-masing harus mereferensikan struktur WSAOVERLAPPED terpisah.
Jika parameter lpCompletionRoutineadalah NULL, parameter hEventdari lpOverlapped diberi sinyal ketika operasi yang tumpang tindih selesai jika berisi handel objek peristiwa yang valid. Aplikasi dapat menggunakan WSAWaitForMultipleEvents atau WSAGetOverlappedResult untuk menunggu atau melakukan polling pada objek peristiwa.
Jika lpCompletionRoutine bukan NULL, parameter hEvent diabaikan dan dapat digunakan oleh aplikasi untuk meneruskan informasi konteks ke rutinitas penyelesaian. Penelepon yang melewati lpCompletionRoutinenon-NULL dan kemudian memanggil WSAGetOverlappedResult untuk permintaan I/O yang tumpang tindih yang sama mungkin tidak mengatur parameter fWait untuk pemanggilan WSAGetOverlappedResult ke TRUE. Dalam hal ini penggunaan parameter hEvent tidak terdefinisi, dan mencoba menunggu parameter hEvent akan menghasilkan hasil yang tidak dapat diprediksi.
Rutinitas penyelesaian mengikuti aturan yang sama seperti yang ditetapkan untuk rutinitas penyelesaian I/O file Windows. Rutinitas penyelesaian tidak akan dipanggil sampai utas berada dalam status tunggu yang dapat diperingatkan seperti dapat terjadi ketika fungsi WSAWaitForMultipleEvents dengan parameter fAlertable diatur ke TRUE dipanggil.
Jika port penyelesaian IO digunakan dan parameter lpCompletionRoutine dan parameter hEventadalah NULL, hasil operasi adalah jadwal pada port penyelesaian IO. Ini terjadi untuk semua operasi yang berhasil, apakah operasi segera selesai atau tidak.
Penyedia transportasi memungkinkan aplikasi untuk memanggil operasi kirim dan terima dari dalam konteks rutinitas penyelesaian I/O soket, dan menjamin bahwa, untuk soket tertentu, rutinitas penyelesaian I/O tidak akan bersarang. Ini memungkinkan transmisi data sensitif waktu terjadi sepenuhnya dalam konteks preemptive.
Prototipe rutinitas penyelesaian adalah sebagai berikut.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
CompletionRoutine adalah tempat penampung untuk nama fungsi yang ditentukan aplikasi atau yang ditentukan pustaka. dwError menentukan status penyelesaian untuk operasi yang tumpang tindih seperti yang ditunjukkan oleh lpOverlapped. cbTransferred menentukan jumlah byte yang diterima. Parameter dwFlags berisi informasi yang akan muncul di lpFlags jika operasi penerimaan telah selesai segera. Fungsi ini tidak mengembalikan nilai.
Mengembalikan dari fungsi ini memungkinkan pemanggilan rutinitas penyelesaian lain yang tertunda untuk soket ini. Saat menggunakan WSAWaitForMultipleEvents, semua rutinitas penyelesaian menunggu dipanggil sebelum penantian utas yang dapat diperingatkan dipenuhi dengan kode pengembalian WSA_IO_COMPLETION. Rutinitas penyelesaian dapat dipanggil dalam urutan apa pun, tidak harus dalam urutan yang sama operasi yang tumpang tindih selesai. Namun, buffer yang diposting dijamin akan diisi dalam urutan yang sama dengan yang ditentukan.
Contoh Kode
Contoh berikut menunjukkan penggunaan fungsi WSARecvFrom .#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
int __cdecl main()
{
WSADATA wsaData;
WSABUF DataBuf;
WSAOVERLAPPED Overlapped;
SOCKET RecvSocket = INVALID_SOCKET;
struct sockaddr_in RecvAddr;
struct sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
u_short Port = 27015;
char RecvBuf[1024];
int BufLen = 1024;
DWORD BytesRecv = 0;
DWORD Flags = 0;
int err = 0;
int rc;
int retval = 0;
//-----------------------------------------------
// Initialize Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
/* Could not find a usable Winsock DLL */
wprintf(L"WSAStartup failed with error: %ld\n", rc);
return 1;
}
// Make sure the Overlapped struct is zeroed out
SecureZeroMemory((PVOID) &Overlapped, sizeof(WSAOVERLAPPED) );
// Create an event handle and setup the overlapped structure.
Overlapped.hEvent = WSACreateEvent();
if (Overlapped.hEvent == NULL) {
wprintf(L"WSACreateEvent failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = WSASocket(AF_INET,
SOCK_DGRAM,
IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (RecvSocket == INVALID_SOCKET) {
/* Could not open a socket */
wprintf(L"WSASocket failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
rc = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (rc != 0) {
/* Bind to the socket failed */
wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
DataBuf.len = BufLen;
DataBuf.buf = RecvBuf;
wprintf(L"Listening for incoming datagrams on port=%d\n", Port);
rc = WSARecvFrom(RecvSocket,
&DataBuf,
1,
&BytesRecv,
&Flags,
(SOCKADDR *) & SenderAddr,
&SenderAddrSize, &Overlapped, NULL);
if (rc != 0) {
err = WSAGetLastError();
if (err != WSA_IO_PENDING) {
wprintf(L"WSARecvFrom failed with error: %ld\n", err);
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
else {
rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
retval = 1;
}
rc = WSAGetOverlappedResult(RecvSocket, &Overlapped, &BytesRecv,
FALSE, &Flags);
if (rc == FALSE) {
wprintf(L"WSArecvFrom failed with error: %d\n", WSAGetLastError());
retval = 1;
}
else
wprintf(L"Number of received bytes = %d\n", BytesRecv);
wprintf(L"Finished receiving. Closing socket.\n");
}
}
//---------------------------------------------
// When the application is finished receiving, close the socket.
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
wprintf(L"Exiting.\n");
//---------------------------------------------
// Clean up and quit.
WSACleanup();
return (retval);
}
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 |