Fungsi WSASend (winsock2.h)
Fungsi WSASend mengirim data pada soket yang terhubung.
Sintaks
int WSAAPI WSASend(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameter
[in] s
Deskriptor yang mengidentifikasi soket yang tersambung.
[in] lpBuffers
Penunjuk ke array struktur WSABUF . Setiap struktur WSABUF berisi penunjuk ke buffer dan panjangnya, dalam byte, dari buffer. Untuk aplikasi Winsock, setelah fungsi WSASend dipanggil, sistem memiliki buffer ini dan aplikasi mungkin tidak mengaksesnya. Array ini harus tetap valid selama durasi operasi pengiriman.
[in] dwBufferCount
Jumlah struktur WSABUF dalam array lpBuffers .
[out] lpNumberOfBytesSent
Penunjuk ke nomor, dalam byte, yang dikirim oleh panggilan ini jika operasi I/O 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] dwFlags
Bendera yang digunakan untuk mengubah perilaku panggilan fungsi WSASend . Untuk informasi selengkapnya, lihat Menggunakan dwFlags di bagian Keterangan.
[in] lpOverlapped
Penunjuk ke struktur WSAOVERLAPPED . Parameter ini diabaikan untuk soket yang tidak tumpang tindih.
[in] lpCompletionRoutine
Jenis: LPWSAOVERLAPPED_COMPLETION_ROUTINE _In_opt_
Penunjuk ke rutinitas penyelesaian yang dipanggil ketika operasi pengiriman telah selesai. Parameter ini diabaikan untuk soket yang tidak tumpang tindih.
Mengembalikan nilai
Jika tidak ada kesalahan yang terjadi dan operasi pengiriman telah segera selesai, WSASend mengembalikan nol. Dalam hal ini, rutinitas penyelesaian akan 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 dihentikan karena waktu habis atau kegagalan lainnya. | |
Untuk soket aliran, sirkuit virtual direset oleh sisi jarak jauh. Aplikasi harus menutup soket karena tidak lagi dapat digunakan. Untuk soket datagram UDP, kesalahan ini akan menunjukkan bahwa operasi pengiriman sebelumnya menghasilkan pesan "Port Unreachable" ICMP. | |
Parameter lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine tidak sepenuhnya terkandung dalam bagian ruang alamat pengguna yang valid. | |
Panggilan Windows Socket 1.1 pemblokiran dibatalkan melalui WSACancelBlockingCall. | |
Pemblokiran panggilan Windows Sockets 1.1 sedang berlangsung, atau penyedia layanan masih memproses fungsi panggilan balik. | |
Soket belum terikat dengan ikatan atau soket tidak dibuat dengan bendera tumpang tindih. | |
Soket berorientasi pesan, dan pesan lebih besar dari maksimum yang didukung oleh transportasi yang mendasar. | |
Subsistem jaringan gagal. | |
Untuk soket aliran, koneksi telah terputus karena aktivitas tetap aktif mendeteksi kegagalan saat operasi sedang berlangsung. Untuk soket datagram, kesalahan ini menunjukkan bahwa waktu hidup telah kedaluwarsa. | |
Penyedia Windows Sockets melaporkan kebuntuan buffer. | |
Soket tidak tersambung. | |
Deskriptor bukan soket. | |
MSG_OOB ditentukan, tetapi soket tidak bergaya aliran seperti jenis SOCK_STREAM, data OOB tidak didukung di domain komunikasi yang terkait dengan soket ini, MSG_PARTIAL tidak didukung, atau soket tidak langsung dan hanya mendukung operasi penerimaan. | |
Soket telah dimatikan; tidak dimungkinkan untuk WSASend pada soket setelah pematian dipanggil dengan cara diatur ke SD_SEND atau SD_BOTH. | |
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 pengiriman tidak dapat segera diselesaikan. |
|
Panggilan WSAStartup yang berhasil harus terjadi sebelum menggunakan fungsi ini. | |
Operasi yang tumpang tindih berhasil dimulai dan penyelesaian akan ditunjukkan di lain waktu. | |
Operasi yang tumpang tindih telah dibatalkan karena penutupan soket, eksekusi perintah "SIO_FLUSH" di WSAIoctl, atau utas yang memulai permintaan yang tumpang tindih keluar sebelum operasi selesai. Untuk informasi selengkapnya, lihat bagian Keterangan. |
Keterangan
Fungsi WSASend menyediakan fungsionalitas di atas dan di atas fungsi pengiriman standar di dua area penting:
- Ini dapat digunakan bersama dengan soket yang tumpang tindih untuk melakukan operasi pengiriman yang tumpang tindih.
- Ini memungkinkan beberapa buffer pengiriman ditentukan sehingga berlaku untuk jenis I/O yang tersebar/kumpulkan.
Soket yang dibuat oleh fungsi soket akan memiliki atribut yang tumpang tindih sebagai default. Soket yang dibuat oleh fungsi WSASocket dengan parameter dwFlags yang diteruskan ke WSASocket dengan set bit WSA_FLAG_OVERLAPPED akan memiliki atribut yang tumpang tindih. Untuk soket dengan atribut yang tumpang tindih, WSASend menggunakan I/O yang tumpang tindih kecuali parameter lpOverlapped dan lpCompletionRoutine adalah NULL. Dalam hal ini, soket diperlakukan sebagai soket yang tidak tumpang tindih. Indikasi penyelesaian akan terjadi, memanggil penyelesaian rutinitas atau pengaturan objek peristiwa, ketika buffer telah dikonsumsi oleh transportasi. Jika operasi tidak segera selesai, status penyelesaian akhir diambil melalui rutinitas penyelesaian atau WSAGetOverlappedResult.
Jika lpOverlapped dan lpCompletionRoutineADALAH NULL, soket dalam fungsi ini akan diperlakukan sebagai soket yang tidak tumpang tindih.
Untuk soket yang tidak tumpang tindih, dua parameter terakhir (lpOverlapped, lpCompletionRoutine) diabaikan dan WSASend mengadopsi semantik pemblokiran yang sama seperti yang dikirim. Data disalin dari buffer ke dalam buffer transportasi. Jika soket tidak memblokir dan berorientasi aliran, dan tidak ada ruang yang cukup dalam buffer transportasi, WSASend akan kembali dengan hanya sebagian dari buffer aplikasi yang telah dikonsumsi. Mengingat situasi buffer yang sama dan soket pemblokiran, WSASend akan memblokir sampai semua konten buffer aplikasi telah dikonsumsi.
Untuk soket berorientasi pesan, jangan melebihi ukuran pesan maksimum penyedia yang mendasar, yang dapat diperoleh dengan mendapatkan nilai opsi soket SO_MAX_MSG_SIZE. Jika data terlalu panjang untuk diteruskan secara atomik melalui protokol yang mendasar, kesalahan WSAEMSGSIZE dikembalikan, dan tidak ada data yang dikirimkan.
Windows Me/98/95: Fungsi WSASend tidak mendukung lebih dari 16 buffer.
Menggunakan dwFlags
Parameter dwFlags 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 dwFlags . Yang terakhir dibangun dengan menggunakan operator bitwise OR dengan salah satu nilai yang tercantum dalam tabel berikut.Nilai | Makna |
---|---|
MSG_DONTROUTE | Menentukan bahwa data tidak boleh tunduk pada perutean. Penyedia layanan Windows Sockets dapat memilih untuk mengabaikan bendera ini. |
MSG_OOB | Kirim data OOB pada soket bergaya stream seperti SOCK_STREAM saja. |
MSG_PARTIAL | Menentukan bahwa lpBuffers hanya berisi pesan parsial. Ketahuilah bahwa kode kesalahan WSAEOPNOTSUPP akan dikembalikan oleh transportasi yang tidak mendukung transmisi pesan parsial. |
I/O Soket Tumpang Tindih
Jika operasi yang tumpang tindih segera selesai, WSASend mengembalikan nilai nol dan parameter lpNumberOfBytesSent diperbarui dengan jumlah byte yang dikirim. Jika operasi yang tumpang tindih berhasil dimulai dan akan selesai nanti, WSASend mengembalikan SOCKET_ERROR dan menunjukkan kode kesalahan WSA_IO_PENDING. Dalam hal ini, lpNumberOfBytesSent 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.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 lpCompletionRoutine adalah 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.
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 ditumpuk. Ini memungkinkan transmisi data sensitif waktu terjadi sepenuhnya dalam konteks preemptive.
Contoh kode C++ berikut adalah prototipe dari rutinitas penyelesaian.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
Fungsi CompletionRoutine adalah tempat penampung untuk nama fungsi yang ditentukan aplikasi atau yang ditentukan pustaka. Parameter dwError menentukan status penyelesaian untuk operasi yang tumpang tindih seperti yang ditunjukkan oleh lpOverlapped. cbTransferred menentukan jumlah byte yang dikirim. Saat ini tidak ada nilai bendera yang ditentukan dan dwFlags akan menjadi nol. Fungsi ini tidak mengembalikan nilai.
Mengembalikan dari fungsi ini memungkinkan pemanggilan rutinitas penyelesaian lain yang tertunda untuk soket ini. Semua rutinitas penyelesaian menunggu dipanggil sebelum penantian utas yang dapat diperingatkan terpenuhi 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 dikirim dalam urutan yang sama dengan yang ditentukan.
Urutan panggilan yang dilakukan ke WSASend juga merupakan urutan di mana buffer ditransmisikan ke lapisan transportasi. WSASend tidak boleh dipanggil pada soket berorientasi aliran yang sama secara bersamaan dari utas yang berbeda, karena beberapa penyedia Winsock dapat membagi permintaan pengiriman besar menjadi beberapa transmisi, dan ini dapat menyebabkan data yang tidak diinginkan diselingi dari beberapa permintaan pengiriman bersamaan pada soket berorientasi aliran yang sama.
Contoh Kode
Contoh kode berikut menunjukkan cara menggunakan fungsi WSASend dalam mode I/O yang tumpang tindih.#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define DATA_BUFSIZE 4096
#define SEND_COUNT 10
int __cdecl main()
{
WSADATA wsd;
struct addrinfo *result = NULL;
struct addrinfo hints;
WSAOVERLAPPED SendOverlapped;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD SendBytes;
DWORD Flags;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc, i;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID) & hints, sizeof(struct addrinfo));
// Initialize the hints to obtain the
// wildcard bind address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
rc = getaddrinfo(NULL, "27015", &hints, &result);
if (rc != 0) {
printf("getaddrinfo failed with error: %d\n", rc);
return 1;
}
ListenSocket = socket(result->ai_family,
result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
return 1;
}
rc = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
rc = listen(ListenSocket, 1);
if (rc == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
// Accept an incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
printf("Client Accepted...\n");
// Make sure the SendOverlapped struct is zeroed out
SecureZeroMemory((PVOID) & SendOverlapped, sizeof (WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
SendOverlapped.hEvent = WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 1;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for (i = 0; i < SEND_COUNT; i++) {
rc = WSASend(AcceptSocket, &DataBuf, 1,
&SendBytes, 0, &SendOverlapped, NULL);
if ((rc == SOCKET_ERROR) &&
(WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASend failed with error: %d\n", err);
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE,
TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
break;
}
rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &SendBytes,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
printf("Wrote %d bytes\n", SendBytes);
WSAResetEvent(SendOverlapped.hEvent);
}
WSACloseEvent(SendOverlapped.hEvent);
closesocket(AcceptSocket);
closesocket(ListenSocket);
freeaddrinfo(result);
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 |