Thursday, 5 October 2017

Winsock Send Data Binære Alternativer


Sende binær data via UDP-protokoll (Winsock) Jeg lager et klientprogram som krever binær data som skal sendes til serveren via UDP-protokollen. (Jeg bruker winsock kontrollen) Jeg har brukt følgende kode. Dim ByteX som Byte Dim X så lenge Dim FileX som Interger Winsock3.LocalPort 10000 Winsock3.RemoteHost 211.233.70.51 Winsock3.RemotePort 9500 FileX FreeFile Åpne App. Path udp1.dat for Binær som FileX X 1 Gjør til X FileLen (App. Path udp1.dat) 1 Hent FileX. X, ByteX Winsock3.SendData ByteX X X 1 Loop Lukk FileX Når jeg sender data på denne måten, sender den 52 pakker som inneholder 1 byte hver i stedet for 1 pakke som inneholder 52 byte. Denne koden fungerer riktig for TCP-protokollen, men UDP virker ikke det samme. Hvordan kan jeg sende binære data ved hjelp av UDP-protokollen som bare sender 1 pakke data Jeg lager et klientprogram som krever binær data som skal sendes til serveren via UDP-protokollen. (Jeg bruker winsock kontrollen):: Jeg har brukt følgende kode. :: Dim ByteX som byte: Dim X så lenge: Dim FileX som Interger:: Winsock3.LocalPort 10000: Winsock3.RemoteHost 211.233.70.51: Winsock3.RemotePort 9500:: FileX FreeFile: Åpne App. Path udp1.dat for Binær som FileX : X 1: Gjør til X FileLen (App. Path udp1.dat) 1: Hent FileX. X, ByteX: Winsock3.SendData ByteX: X X 1: Loop: Lukk FileX:: Når jeg sender data på denne måten, sender den 52 pakker som inneholder 1 byte hver i stedet for 1 pakke som inneholder 52 byte. Denne koden fungerer riktig for TCP-protokollen, men UDP virker ikke det samme. Hvordan kan jeg sende binære data ved hjelp av UDP-protokollen som bare sender 1 pakke data: Hei Prøv denne Winsock3.Protocol sckUDPProtocol Winsock har sckTCPProtocol som standard .. lillaDont ta livet for alvor, uansett vil du ikke unnslippe live fra itpurplesending binære data ved hjelp av winsock Im beklager, sier du at jeg må bruke Datagram i stedet for Stream Sockets for å få dette arbeidet jeg bruker SOCKSTREAM akkurat nå, og jeg foretrekker å bli med det. Er det noen måte å få dette til å akseptere 0x00 og akseptere data etter det, mens du fortsatt bruker strømkontakter. Igjen, takk for all din hjelp. mikyu Hmm, det er rart. Jeg trodde at SOCKDGRAM-argumentet skulle angi binære data, i motsetning til SOCKSTREAM. : Recv skal lese utover nuller i det tilfellet. : Er du sikker på at du ikke fanger dataene i en strengdatatype som du skriver ut eller skriver til en fil eller noe med en av str-rutinene: Jeg mener, er du sikker på at du viser mottatte data riktig Beklager, sier du at jeg må bruke Datagram i stedet for Stream Sockets for å få dette arbeidet, bruker jeg SOCKSTREAM akkurat nå, og jeg foretrekker å være med. Er det noen måte å få dette til å akseptere 0x00 og akseptere data etter det, mens du fortsatt bruker strømkontakter. Igjen, takk for all din hjelp. : mikyu:. Hmm, det er rart. Jeg trodde at SOCKDGRAM-argumentet skulle angi binære data, i motsetning til SOCKSTREAM. . Resv burde lese utover nuller i det tilfellet. . Er du sikker på at du ikke fanger dataene i en strengdatatype som du skriver ut eller skriver til en fil eller noe med en av str-rutinene. Jeg mener, er du sikker på at du viser de mottatte dataene riktig: SOCKDGRAM betyr ikke binære data. Det betyr at du vil bruke UDP-protokollen for å sende data og data sendes i datagrammer. SOCKSTREAM betyr at du vil bruke TCP-protokollen og sende data som strøm. Stikkontakt bryr seg ikke hva slags data du sender. Alt du trenger er pekeren til buffer som holder dataene og lengden på bufferen. Null innsiden data betyr ikke noe, det er bare null. Dataene er ikke avsluttet med null da C-strenger er. Stikkontakt bryr seg ikke om innhold av data. Jeg tror det er noe galt med at du mottar kode. Kanskje du bruker null som terminator der, noe som er veldig dårlig. Hvis du kunne post kode som mottar data her, kunne jeg prøve å finne ut hva som er galt med det. Her er koden jeg bruker. Igjen, jeg er ny på winsock så vær så snill å bære med meg. Takk kode int server (tom) unsigned char recmsg3072 SOCKET serverfd, clientfd listen på sockfd, ny tilkobling på newfd SOCKADDRIN serveraddr SOCKADDRIN clientaddr int len ​​int j int msgsize 0 kar spørsmålet WSADATA wsadata usigned short verrequest FILMike LINGER LingVar verrequest MAKEWORD (2,2 ) hvis (WSAStartup (verrequest, ampwsadata) -1) printf (Kunne ikke finne en brukbar Winsock DLL) exit (1) hvis ((serverfd socket (AFINET, SOCKSTREAM, 0)) -1) perror (SERVER SIDE: kan ikke åpne socket) LingVar. lonoff TRUE LingVar. llinger 0 hvis (setockopt (serverfd, SOLSOCKET, SOOOBINLINE, (char FAR) ampLingVar, sizeof (LingVar)) -1) perror (SERVER SIDE: kunne ikke utføre setockopt) exit (1) serveraddr. sinfamily AFINET serveraddr. sinport htons (SERVERPORT) serveraddr. sinaddr. saddr htonl (INADDRANY) memset (amp (serveraddr. sinzero), 8) hvis (bind (serverfd, (struct sockaddr) ampserveraddr, sizeof (serveraddr)) -1) perror SIDE: kan ikke binde port) exit (1) hvis (lytt (serverfd, PACKETQUEUE) -1) per ror (SERVER SIDE: kan ikke lytte til stikkontakt) avslutte (1) memset (recmsg, 0x0, 3072) mens (1) printf (Spørsmål) spørre getchar (spørsmål N spørsmål n) retur 0 printf (SERVER SIDE: Venter på data på port) len sizeof (clientaddr) clientfd acceptere (serverfd, (struct sockaddr) ampclientaddr, amplen) hvis (clientfd -1) perror (SERVER SIDE: kan ikke akseptere tilkobling) returnere ERROR printf (SERVER SIDE: mottatt tilkobling fra: s, inetntoa (clientaddr. sinaddr)) msgsize readline (recmsg, clientfd, clientaddr) hvis (msgsize ERROR) printf (SERVER SIDE: Kunne ikke lese meldingen) coutltltthis er meldingsstørrelse : (ls), (resmsg, sizeof (short int), 10, mike) for (j0 jlt10 j) printf (- c, recmsgj) closesocket (clientfd) hvis (WSACleanup () -1) perror (Problem med WSACLEANUP) 1) int readline (unsigned char buf, SOCKET sd, SOCKADDRIN clientaddr) char segMAXDATA int offset 0 int res 1 int cliLen memset (seg, 0x0, MAXDATA) cliL (size) () seg, res) offset res memset (seg, 0x0, MAXDATA) return ERROR-kode: SOCKDGRAM betyr ikke binære data. Det betyr at du vil bruke UDP-protokollen for å sende data og data sendes i datagrammer. SOCKSTREAM betyr at du vil bruke TCP-protokollen og sende data som strøm. :: Socket bryr seg ikke hva slags data du sender. Alt du trenger er pekeren til buffer som holder dataene og lengden på bufferen. :: Null inne data betyr ikke noe, det er bare null. Dataene er ikke avsluttet med null da C-strenger er. Stikkontakt bryr seg ikke om innhold av data. :: Jeg tror det er noe galt med at du mottar kode. Kanskje du bruker null som terminator der, noe som er veldig dårlig. Hvis du kunne post kode som mottar data her, kunne jeg prøve å finne ut hva som er galt med det. : En Intro til Windows Socket Programmering med C Hva har vi i dette kapittelet 1 del 4 Datatransmisjon send () og WSASend () WSASendDisconnect () Utgående banddata recv () og WSARecv () WSARecvDisconnect () Stream protokoller Spredere - Gather IO Breaking Connection-avslutningen () clossocket () TCP ReceiverServer Med velg () Eksempel Datatransmisjon send () og WSASend () WSASendDisconnect () Utgående banddata recv () og WSARecv () Mottaksforespørselen utføres bare når en av følgende hendelser oppstår: Bufferen som er levert av den som ringer er fullstendig full. Tilkoblingen er stengt. Forespørselen er kansellert eller det oppstod en feil. Merk at hvis den underliggende transporten ikke støtter MSGWAITALL, eller hvis stikkontakten er i ikke-blokkeringsmodus, feiler dette samtalen med WSAEOPNOTSUPP. Også, hvis MSGWAITALL er spesifisert sammen med MSGOOB, MSGPEEK eller MSGPARTIAL, vil dette anropet mislykkes med WSAEOPNOTSUPP. Dette flagget støttes ikke på datagramkontakter eller meldingsorienterte CO-kontakter. Selvfølgelig oppgir 0 ingen spesielle handlinger. MSGPEEK forårsaker dataene som er tilgjengelige for å bli kopiert til den medfølgende mottakeren. men disse dataene fjernes ikke fra systembufferen. Antallet av byte som ventes, returneres også. Meldingen er dårlig. Ikke bare forringer ytelsen, da du nå må lage to systemanrop (en til å se og en uten MSGPEEK-flagget for å faktisk fjerne dataene), men det er også upålitelig under visse omstendigheter. Dataene som returneres, kan ikke gjenspeile hele beløpet som er tilgjengelig. Ved å forlate data i systembufferne, har systemet mindre plass til å inneholde innkommende data. Som et resultat reduserer systemet TCP-vinduets størrelse for alle sendere. Dette forhindrer at søknaden din oppnår maksimal mulig gjennomstrømning. Det beste er å kopiere alle dataene du kan inn i din egen buffer og manipulere den der. Det er noen hensyn når du bruker recv () på en meldings - eller datagrambasert stikkontakt som UDP, som vi vil beskrive senere. Hvis dataene som er ventende er større enn den medfølgende bufferen, er bufferen fylt med så mye data som det vil inneholde. I dette tilfellet genererer recv () - samtalen feilen WSAEMSGSIZE. Vær oppmerksom på at meldingsstørrelsesfeilen oppstår med meldingsorienterte protokoller. Stream protokoller som TCP buffer innkommende data, og returnere så mye data som søknadsforespørsler, selv om mengden av ventende data er større. Dermed vil du ikke møte WSAEMSGSIZE-feilen for streaming protokoller. Funksjonen WSARecv () legger til noen nye evner over recv (), som overlappende IO og delvise datagramvarsler. Definisjonen av WSARecv () er: Parameter s er den tilkoblede kontakten. Den andre og tredje parameteren er bufferne for å motta dataene. LpBuffers-parameteren er en rekke WSABUF-strukturer, og dwBufferCount indikerer antall WSABUF-strukturer i arrayet. Parameteren lpNumberOfBytesReceived peker på antall byte mottatt av denne samtalen dersom mottaksoperasjonen fullføres umiddelbart. LpFlags-parameteren kan være en av verdiene MSGPEEK, MSGOOB, eller MSGPARTIAL, eller en bitvis ELLER kombinasjon av disse verdiene. MSGPARTIAL-flagget har flere forskjellige betydninger, avhengig av hvor det brukes eller oppstått. For meldingsorienterte protokoller som støtter delvise meldinger (som AppleTalk), er dette flagget angitt ved retur fra WSARecv () (hvis hele meldingen ikke kunne returneres i denne samtalen på grunn av utilstrekkelig bufferplass). I dette tilfellet angir etterfølgende WSARecv () samtaler dette flagget til hele meldingen returneres, når MSGPARTIAL-flagget slettes. Hvis dette flagget er bestått som en inngangsparameter, bør mottaksoperasjonen fullføres så snart data er tilgjengelig, selv om det bare er en del av hele meldingen. MSGPARTIAL-flagget brukes kun med meldingsorienterte protokoller, ikke med streaming-filer. I tillegg støtter ikke alle protokoller delvise meldinger. Protokolloppføringen for hver protokoll inneholder et flagg som angir om det støtter denne funksjonen. De lpOverlapped og lpCompletionRoutine parametrene brukes i overlappende IO operasjoner, diskutert i andre kapitler. Det er en annen spesialisert mottaksfunksjon du bør være oppmerksom på: WSARecvDisconnect (). WSARecvDisconnect () Denne funksjonen er motsatt av WSASendDisconnect () og er definert som følger: int WSARecvDisconnect (SOCKET s, LPWSABUF lpInboundDisconnectData) Som sin sende motpart er parametrene til WSASendDisconnect () det tilkoblede sokkelhåndtaket og en gyldig WSABUF-struktur med data som skal mottas. Dataene som mottas, kan bare koble fra data som er sendt av en WSASendDisconnect () på den andre siden, det kan ikke brukes til å motta normale data. I tillegg, når dataene er mottatt, deaktiverer denne funksjonen mottak fra den eksterne parten, noe som tilsvarer å kalle avstanden () - funksjonen (som beskrevet senere) med SDRECEIVE. Stream-protokoller Fordi de fleste tilkoblingsorienterte kommunikasjon, for eksempel TCP, er streamingprotokoller, beskriv dem kort her kort. En streaming protokoll er en som avsenderen og mottakeren kan bryte opp eller samle data i mindre eller større grupper. Den følgende figuren beskriver kort strømmen av TCP-pakken mellom klient - og server-sider. Det viktigste å være klar over med enhver funksjon som sender eller mottar data på en strømkontakt, er at du ikke er garantert å lese eller skrive mengden data du ber om. La oss si at du har en tegnbuffer med 2048 byte data du vil sende med send-funksjonen. Koden for å sende dette er: int nBytes 2048 Fyll sendbuff med 2048 bytes data Anta s er en gyldig, tilkoblet strømuttak rett send (s, sendbuff, nBytes, 0) Det er mulig for send å returnere etter å ha sendt mindre enn 2048 byte . Retvariabelen vil bli satt til antall byte sendt fordi systemet tildeler en viss bufferplass for hver kontakt for å sende og motta data. Ved sending av data holder de interne bufferne data som skal sendes til det tidspunkt dataene kan plasseres på ledningen. Flere vanlige situasjoner kan forårsake dette. For eksempel vil overføring av en stor mengde data for eksempel føre til at disse bufferne fylles raskt. Også, for TCPIP, er det det som er kjent som vinduets størrelse (skyvevindudemo). Mottakersiden vil justere denne størrelsesstørrelsen for å angi hvor mye data den kan motta. Hvis mottakeren oversvømmes med data, kan det hende at vinduets størrelse er 0 for å hente opp de ventende dataene. Dette vil tvinge avsenderen til å stoppe til den mottar et nytt vindu størrelse større enn 0. I tilfelle av vårt sendeanrop, kan det være bufferplass for å holde bare 1024 byte, i så fall må du sende de resterende 1024 byte på nytt. Følgende kode sikrer at alle bytesene dine sendes: int nBytes 2048, nLeft, idx Fyll sendbuff med 2048 byte data mens (nLeft gt 0) Anta at s er en gyldig tilkoblet strømkontakt Ting blir litt komplisert hvis meldingsstørrelsene varierer . Det er nødvendig å legge inn din egen protokoll for å la mottakeren vite hvor stor den kommende meldingen vil være. For eksempel vil de første fire bytesene som er skrevet til mottakeren, alltid være heltallstørrelsen i byte av den kommende meldingen. Mottakeren starter hver avlesning ved å se på de første fire bytesene, konvertere dem til et heltall og bestemme hvor mange ekstra byte meldingen består av. Scatter-Gather IO Scatter-gather-støtte er et konsept som opprinnelig ble introdusert i Berkeley Sockets med funksjonene recv og writev. Denne funksjonen er tilgjengelig med Winsock 2-funksjonene WSARecv (), WSARecvFrom (), WSASend () og WSASendTo (). Det er mest nyttig for programmer som sender og mottar data som er formatert på en svært spesifikk måte. For eksempel kan meldinger fra en klient til en server alltid være sammensatt av en fast 32-byte header som angir noe operasjon, etterfulgt av en 64-byte datablokke og avsluttet med en 16-byte trailer. I dette eksemplet kan WSASend () kalles med en rekke tre WSABUF-strukturer, hver som svarer til de tre meldingstyper. På mottakersiden kalles WSARecv () med tre WSABUF-strukturer, som hver inneholder databuffere på 32 byte, 64 byte og 16 byte. Når du bruker strømbaserte stikkontakter, behandler scatter-gather operasjoner bare de medfølgende databuffere i WSABUF-strukturer som en sammenhengende buffer. Mottakssamtalen kan også returnere før alle buffere er fulle. På meldingsbaserte stikkontakter mottar hver samtale til en mottaksoperasjon en enkelt melding opp til den medfølgende bufferstørrelsen. Hvis bufferplassen ikke er tilstrekkelig, svinger samtalen med WSAEMSGSIZE, og dataene avkortes for å passe til ledig plass. Selvfølgelig, med protokoller som støtter delvise meldinger, kan MSGPARTIAL-flagget brukes til å forhindre tap av data. Bryte tilkoblingen Når du er ferdig med en stikkontakt, må du lukke den og frigjøre ressurser som er knyttet til det stikkontakten. For å frigjøre ressursene som er forbundet med et åpent sokkelhåndtak, bruk lukkekontakten (). Vær imidlertid oppmerksom på at closesocket () kan ha noen bivirkninger, avhengig av hvordan det kalles, som kan føre til tap av data. Av denne grunn bør en tilkobling bli grasiøst avsluttet med funksjonen shutdown () før en samtale til clossocket () - funksjonen. Disse to API-funksjonene blir diskutert neste. Avslutting () For å sikre at alle dataene som sendes av en bruker, mottas av juryen, bør en velskrevet søknad varsle mottakeren om at ingen data skal sendes. På samme måte bør jevnaldrende gjøre det samme. Dette er kjent som en grasiøs nær og utføres av shutdown () - funksjonen, definert som: int shutdown (SOCKET s, int how) Hvordan parameteren kan være SDRECEIVE, SDSEND eller SDBOTH. For SDRECEIVE blir etterfølgende anrop til en mottaksfunksjon på stikkontakten ugyldig. Dette har ingen effekt på de nederste protokollagene. Og for TCP-kontakter, hvis data er i kø for mottak eller hvis data kommer senere, blir tilkoblingen tilbakestilt. Men på UDP-stikkontakter er innkommende data fortsatt akseptert og i kø (fordi shutdown () har ingen betydning for forbindelsesløse protokoller). For SDSEND er etterfølgende anrop til en hvilken som helst sendefunksjon ugyldig. For TCP-stikkontakter fører dette til at en FIN-pakke genereres etter at alle data er sendt og bekreftet av mottakeren. Til slutt deaktiverer SDBOTH både å sende og motta. Vær oppmerksom på at ikke alle tilkoblingsorienterte protokoller støtter grasiøs nedleggelse, som er hva avbrytingsprogrammet () utfører. For disse protokollene (for eksempel ATM), bare lukkes lås () må kalles for å avslutte økten. Et flagg som beskriver hvilke typer operasjoner er oppsummert i følgende tabell. Mulige verdier for dette flagget er oppført i Winsock2.h headerfilen. Når funksjonen shutdown () er slått av for å deaktivere send, mottak eller begge deler, er det ingen metode for å aktivere send eller motta for eksisterende socketforbindelse. En søknad bør ikke stole på at du kan gjenbruke en stikkontakt etter at den er stengt. Spesielt er det ikke nødvendig med en Windows Sockets-leverandør for å støtte bruken av tilkobling () på en stikkontakt som er stengt. Hvis en applikasjon vil gjenbruke en stikkontakt, skal funksjonen DisconnectEx () kalles med dwFlags-parameterinnstillingen til TFREUSESOCKET for å lukke en tilkobling på en stikkontakt og forberede stikkontakten som skal gjenbrukes. Når forespørselen fra DisconnectEx () er fullført, kan stikkhåndtaket sendes til AcceptEx () eller ConnectEx () - funksjonen. Hvis et program ønsker å gjenbruke en kontakt, kan funksjonene TransmitFile () eller TransmitPackets () kalles med dwFlags-parametersettet med TFDISCONNECT og TFREUSESOCKET for å koble fra etter at alle dataene har vært i kø for overføring og forberede stikkontakten som skal gjenbrukes. Når TransmitFile () - forespørselen er fullført, kan sokkelhåndtaket sendes til funksjonssamtalen som tidligere ble brukt for å etablere forbindelsen, for eksempel AcceptEx () eller ConnectEx (). Når TransmitPackets () - funksjonen er fullført, kan sokkelhåndtaket overføres til AcceptEx () - funksjonen. Vær oppmerksom på at stikkontakten kobles fra under utførelsen av den underliggende transporten. For eksempel kan en TCP-stikkontakt være underlagt TCP TIMEWAIT-tilstanden, og forårsake at forsinkelsen av DisconnectEx (), TransmitFile () eller TransmitPackets () - samtalen blir forsinket. lukkekassen () Lukkekassen () - funksjonen lukker en stikkontakt og er definert som: lukkekontakt (SOCKET s) Hvis det ikke oppstår en feil, lukkes stikkontakten () retur null. Ellers returneres en verdi av SOCKETERROR, og en bestemt feilkode kan hentes ved å ringe WSAGetLastError (). Stikkontakten er merket som nonblocking, men lonoff-medlemmet av lingerkonstruksjonen er satt til ikke-null, og linger-delen av lingerstrukturen er satt til en ikke-null timeout-verdi. Calling closesocket () slår ut sokkelbeskrivelsen og eventuelle videre anrop ved hjelp av stikkontakten mislykkes med WSAENOTSOCK. Hvis det ikke er noen andre referanser til denne kontakten, blir alle ressurser knyttet til beskrivelsen utgitt. Dette inkluderer å kaste bort data i køen. Venter på synkronte samtaler utstedt av en hvilken som helst tråd i denne prosessen, blir kansellert uten å legge ut noen varslingsmeldinger. Venter på overlappede operasjoner blir også kansellert. Enhver hendelse, fullføringsrutine eller fullføringsport som er knyttet til overlappingsoperasjonen, utføres, men vil mislykkes med feilen WSAOPERATIONABORTED. I tillegg påvirker en annen faktor oppførselen til closesocket (): om stikkontakten SOLINGER er satt. En applikasjon bør alltid ha et samsvarende anrop for å lukke kontakten () for hvert vellykket anrop til stikkontakten for å returnere eventuelle sokkelressurser til systemet. TCP ReceiverServer Med select () Eksempel 1. Mens du er i Visual C IDE, klikker du Filmeny gt Project submeny for å opprette et nytt prosjekt. 2. Velg Win32 for prosjekttypene: og Win32 Console Application for the Templates. Sett prosjektet og løsningsnavnet. Juster prosjektplasseringen hvis nødvendig, og klikk OK. 3. Klikk på Next for siden Win32 Application Wizard Overview. Vi fjerner alle unødvendige prosjektelementer. 4. På applikasjonssiden, velg Tom prosjekt for tilleggsalternativene. La andre være gitt, og klikk på Fullfør. 5. Deretter må vi legge til ny kildefil. Klikk Prosjektmeny gt Legg til ny undermeny, eller velg prosjektmappen i Solution Explorer gt Velg Legg til meny gt Velg Ny undermeny. 6. Velg C File (.cpp) for maler. Sett kildefilnavnet og klikk på Legg til. Selv om utvidelsen er. cpp, vil Visual C IDE gjenkjenne at kildekoden som brukes, er C basert på Compile as C Code (TC) - alternativet som vil bli angitt på prosjektegenskapssiden senere. 7. Legg til kildekoden som vist nedenfor. En prøve av verdien () returverdi int recvTimeOutTCP (SOCKET socket, lang sek, lang usec)

No comments:

Post a Comment