Bagikan melalui


Fungsi WSASendTo (winsock2.h)

Fungsi WSASendTo mengirim data ke tujuan tertentu, menggunakan I/O yang tumpang tindih jika berlaku.

Sintaks

int WSAAPI WSASendTo(
  [in]  SOCKET                             s,
  [in]  LPWSABUF                           lpBuffers,
  [in]  DWORD                              dwBufferCount,
  [out] LPDWORD                            lpNumberOfBytesSent,
  [in]  DWORD                              dwFlags,
  [in]  const sockaddr                     *lpTo,
  [in]  int                                iTolen,
  [in]  LPWSAOVERLAPPED                    lpOverlapped,
  [in]  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Parameter

[in] s

Deskriptor yang mengidentifikasi soket (mungkin terhubung).

[in] lpBuffers

Penunjuk ke array struktur WSABUF . Setiap struktur WSABUF berisi penunjuk ke buffer dan panjang buffer, dalam byte. Untuk aplikasi Winsock, setelah fungsi WSASendTo 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 jumlah 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 WSASendTo .

[in] lpTo

Penunjuk opsional ke alamat soket target dalam struktur SOCKADDR .

[in] iTolen

Ukuran, dalam byte, dari alamat dalam parameter lpTo .

[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 pengiriman telah selesai (diabaikan untuk soket yang tidak tumpang tindih).

Mengembalikan nilai

Jika tidak ada kesalahan yang terjadi dan operasi pengiriman telah segera selesai, WSASendTo 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
WSAEACCES
Alamat yang diminta adalah alamat siaran, tetapi bendera yang sesuai tidak ditetapkan.
WSAEADDRNOTAVAIL
Alamat jarak jauh bukan alamat yang valid (seperti ADDR_ANY).
WSAEAFNOSUPPORT
Alamat dalam keluarga yang ditentukan tidak dapat digunakan dengan soket ini.
WSAECONNRESET
Untuk soket datagram UDP, kesalahan ini akan menunjukkan bahwa operasi pengiriman sebelumnya menghasilkan pesan ICMP "Port Unreachable".
WSAEDESTADDRREQ
Alamat tujuan diperlukan.
WSAEFAULT
Parameter lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, atau lpCompletionRoutine bukan bagian dari ruang alamat pengguna, atau parameter lpTo terlalu kecil.
WSAEHOSTUNREACH
Operasi soket dicoba ke host yang tidak dapat dijangkau.
WSAEINPROGRESS
Panggilan Windows Sockets 1.1 yang diblokir sedang berlangsung, atau penyedia layanan masih memproses fungsi panggilan balik.
WSAEINTR
Panggilan Windows Socket 1.1 pemblokiran dibatalkan melalui WSACancelBlockingCall.
WSAEINVAL
Soket belum terikat dengan ikatan, atau soket tidak dibuat dengan bendera tumpang tindih.
WSAEMSGSIZE
Soket berorientasi pada pesan, dan pesan lebih besar dari maksimum yang didukung oleh transportasi yang mendasar.
WSAENETDOWN
Subsistem jaringan gagal.
WSAENETRESET
Untuk soket datagram, kesalahan ini menunjukkan bahwa waktu hidup telah kedaluwarsa.
WSAENETUNREACH
Jaringan tidak dapat dijangkau dari host ini saat ini.
WSAENOBUFS
Penyedia Soket Windows melaporkan kebuntuan buffer.
WSAENOTCONN
Soket tidak tersambung (hanya soket berorientasi koneksi).
WSAENOTSOCK
Deskriptor bukan soket.
WSAESHUTDOWN
Soket telah dimatikan; tidak dimungkinkan untuk WSASendTo pada soket setelah pematian dipanggil dengan cara diatur ke SD_SEND atau SD_BOTH.
WSAEWOULDBLOCK
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.

WSANOTINITIALISED
Panggilan WSAStartup yang berhasil harus terjadi sebelum menggunakan fungsi ini.
WSA_IO_PENDING
Operasi yang tumpang tindih berhasil dimulai dan penyelesaian akan ditunjukkan di lain waktu.
WSA_OPERATION_ABORTED
Operasi yang tumpang tindih telah dibatalkan karena penutupan soket, atau eksekusi perintah SIO_FLUSH di WSAIoctl.

Keterangan

Fungsi WSASendTo menyediakan fitur yang disempurnakan melalui fungsi sendto 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.
Fungsi WSASendTo biasanya digunakan pada soket tanpa koneksi yang ditentukan oleh s untuk mengirim datagram yang terkandung dalam satu atau beberapa buffer ke soket peer tertentu yang diidentifikasi oleh parameter lpTo . Bahkan jika soket tanpa koneksi sebelumnya telah terhubung menggunakan fungsi sambungkan ke alamat tertentu, lpTo mengambil alih alamat tujuan hanya untuk datagram tertentu. Pada soket berorientasi koneksi, parameter lpTo dan iToLen diabaikan; dalam hal ini, WSASendTo setara dengan WSASend.

Untuk soket yang tumpang tindih (dibuat menggunakan WSASocket dengan bendera WSA_FLAG_OVERLAPPED) mengirim data menggunakan I/O yang tumpang tindih, kecuali jika lpOverlapped dan lpCompletionRoutine adalah NULL dalam hal ini soket diperlakukan sebagai soket yang tidak tumpang tindih. Indikasi penyelesaian akan terjadi (memanggil rutinitas penyelesaian atau pengaturan objek peristiwa) ketika buffer telah dikonsumsi oleh transportasi. Jika operasi tidak segera selesai, status penyelesaian akhir diambil melalui rutinitas penyelesaian atau WSAGetOverlappedResult.

Catatan Jika soket dibuka, panggilan setsockopt dilakukan, dan kemudian panggilan sendto dilakukan, Windows Sockets melakukan panggilan fungsi ikatan implisit.
 
Jika lpOverlapped dan lpCompletionRoutine adalah 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 WSASendTo mengadopsi semantik pemblokiran yang sama seperti yang dikirim. Data disalin dari buffer ke dalam buffer transportasi. Jika soket tidak diblokir dan dialirkan berorientasi, dan tidak ada ruang yang cukup di buffer transportasi, WSASendTo hanya menampilkan bagian dari buffer aplikasi yang telah dikonsumsi. Mengingat situasi buffer yang sama dan soket pemblokiran, WSASendTo akan memblokir sampai semua konten buffer aplikasi telah dikonsumsi.

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 soket berorientasi pesan, perawatan harus dilakukan agar tidak melebihi ukuran pesan maksimum dari transportasi 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.

Jika soket tidak terikat, nilai unik ditetapkan ke asosiasi lokal oleh sistem, dan soket kemudian ditandai sebagai terikat.

Jika soket tersambung, fungsi getsockname dapat digunakan untuk menentukan alamat IP lokal dan port yang terkait dengan soket.

Jika soket tidak tersambung,
fungsi getsockname dapat digunakan untuk menentukan nomor port lokal yang terkait dengan soket tetapi alamat IP yang dikembalikan diatur ke alamat wildcard untuk protokol yang diberikan (misalnya, INADDR_ANY atau "0.0.0.0" untuk IPv4 dan IN6ADDR_ANY_INIT atau "::" untuk IPv6).

Keberhasilan penyelesaian WSASendTo tidak menunjukkan bahwa data berhasil dikirimkan.

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 Socket dapat memilih untuk mengabaikan bendera ini.
MSG_OOB Kirim data OOB (soket gaya aliran seperti hanya SOCK_STREAM ).
MSG_PARTIAL Menentukan bahwa lpBuffers hanya berisi pesan parsial. Ketahuilah bahwa kode kesalahan WSAEOPNOTSUPP akan dikembalikan oleh transportasi yang tidak mendukung transmisi pesan parsial.
 
Catatan Saat mengeluarkan panggilan Winsock pemblokiran seperti WSASendTo dengan parameter lpOverlapped diatur ke NULL, 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.
 

I/O Soket Tumpang Tindih

Jika operasi yang tumpang tindih segera selesai, WSASendTo mengembalikan nilai nol dan parameter lpNumberOfBytesSent diperbarui dengan jumlah byte yang dikirim. Jika operasi yang tumpang tindih berhasil dimulai dan akan selesai nanti, WSASendTo 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.
Catatan Semua I/O yang dimulai oleh utas tertentu dibatalkan ketika utas tersebut keluar. Untuk soket yang tumpang tindih, operasi asinkron yang tertunda dapat gagal jika utas ditutup sebelum operasi selesai. Lihat ExitThread untuk informasi selengkapnya.
 
Fungsi WSASendTo menggunakan I/O yang tumpang tindih dapat dipanggil dari dalam rutinitas penyelesaian fungsi WSARecv, WSARecvFrom, WSASend, atau WSASendTo sebelumnya. 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 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.

Prototipe rutinitas penyelesaian adalah sebagai berikut.


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. Parameter 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 di mana operasi yang tumpang tindih selesai. Namun, buffer yang diposting dijamin akan dikirim dalam urutan yang sama dengan yang ditentukan.

Contoh Kode

Contoh berikut menunjukkan penggunaan fungsi WSASendTo menggunakan objek peristiwa.
#define WIN32_LEAN_AND_MEAN

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

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

int __cdecl main(int argc, char **argv)
{

    //---------------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    WSABUF DataBuf;

    WSAOVERLAPPED Overlapped;
    SOCKET SendToSocket = INVALID_SOCKET;

    struct sockaddr_in RecvAddr;
    struct sockaddr_in LocalAddr;
    int RecvAddrSize = sizeof (RecvAddr);
    int LocalAddrSize = sizeof (LocalAddr);

    u_short Port = 27777;
    struct hostent *localHost;
    char *ip;
    
    char *targetip;
    char *targetport;

    char SendBuf[1024] = "Data buffer to send";
    int BufLen = 1024;
    DWORD BytesSent = 0;
    DWORD Flags = 0;

    int rc, err;
    int retval = 0;

    // Validate the parameters
    if (argc != 3) {
        printf("usage: %s targetip port\n", argv[0]);
        printf("  to sendto the localhost on port 27777\n");
        printf("       %s 127.0.0.1 27777\n", argv[0]);
        return 1;
    }

    targetip = argv[1];
    targetport = argv[2];

    //---------------------------------------------
    // Initialize Winsock
    // Load Winsock
    rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (rc != 0) {
        printf("Unable to load Winsock: %d\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 == WSA_INVALID_EVENT) {
        printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Create a socket for sending data
    SendToSocket =
        WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
                  WSA_FLAG_OVERLAPPED);
    if (SendToSocket == INVALID_SOCKET) {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACloseEvent(Overlapped.hEvent);
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Set up the RecvAddr structure with the IP address of
    // the receiver (in this example case "123.123.123.1")
    // and the specified port number.
    RecvAddr.sin_family = AF_INET;

    RecvAddr.sin_addr.s_addr = inet_addr(targetip);
    if (RecvAddr.sin_addr.s_addr == INADDR_NONE)  {
        printf("The target ip address entered must be a legal IPv4 address\n");
        WSACloseEvent(Overlapped.hEvent);
        WSACleanup();
        return 1;
    }
    RecvAddr.sin_port = htons( (u_short) atoi(targetport));
    if(RecvAddr.sin_port == 0) {
        printf("The targetport must be a legal UDP port number\n");
        WSACloseEvent(Overlapped.hEvent);
        WSACleanup();
        return 1;
    }

    //---------------------------------------------
    // Set up the LocalAddr structure with the local IP address
    // and the specified port number.
    localHost = gethostbyname("");
    ip = inet_ntoa(*(struct in_addr *) *localHost->h_addr_list);

    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_addr.s_addr = inet_addr(ip);
    LocalAddr.sin_port = htons(Port);

    //---------------------------------------------
    // Bind the sending socket to the LocalAddr structure
    // that has the internet address family, local IP address
    // and specified port number.  
    rc = bind(SendToSocket, (struct sockaddr *) &LocalAddr, LocalAddrSize);
    if (rc == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        WSACloseEvent(Overlapped.hEvent);
        closesocket(SendToSocket);
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Send a datagram to the receiver
    printf("Sending datagram from IPv4 address = %s port=%d\n", 
       inet_ntoa(LocalAddr.sin_addr), ntohs(LocalAddr.sin_port) ); 
    printf("   to IPv4 address = %s port=%d\n", 
       inet_ntoa(RecvAddr.sin_addr), ntohs(RecvAddr.sin_port) ); 

//    printf("Sending a datagram...\n");
    DataBuf.len = BufLen;
    DataBuf.buf = SendBuf;
    rc = WSASendTo(SendToSocket, &DataBuf, 1,
                   &BytesSent, Flags, (SOCKADDR *) & RecvAddr,
                   RecvAddrSize, &Overlapped, NULL);

    if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
        printf("WSASendTo failed with error: %d\n", err);
        WSACloseEvent(Overlapped.hEvent);
        closesocket(SendToSocket);
        WSACleanup();
        return 1;
    }

    rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
    if (rc == WSA_WAIT_FAILED) {
        printf("WSAWaitForMultipleEvents failed with error: %d\n",
                WSAGetLastError());
        retval = 1;
    }

    rc = WSAGetOverlappedResult(SendToSocket, &Overlapped, &BytesSent,
                                FALSE, &Flags);
    if (rc == FALSE) {
        printf("WSASendTo failed with error: %d\n", WSAGetLastError());
        retval = 1;
    }
    else
        printf("Number of sent bytes = %d\n", BytesSent);
        
    //---------------------------------------------
    // When the application is finished sending, close the socket.
    printf("Finished sending. Closing socket.\n");
    WSACloseEvent(Overlapped.hEvent);
    closesocket(SendToSocket);
    printf("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

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

WSACloseEvent

WSACreateEvent

WSAGetOverlappedResult

WSASocket

WSAWaitForMultipleEvents

Fungsi Winsock

Referensi Winsock