Sven hat geschrieben:das geht mich nichts an. Das handelt der TCP/IP-Treiber von Windows aus.
TCP hilft dir bei der Nummerierung und hat 'ne Fehlerkorrektur, das ist schon 'ne ganze Menge. Sehr oft wird auch alles durch gehen was du reinschiebst. Es hat aber schon seinen Sinn daß Funktionen wie "send()" (oder die PB-Ableitungen davon) eine Größe an Bytes zurück geben. Wenn du 100 bytes verschicken willst und dir dein PB-Send sagt da gingen jetzt nur 50 durch dann ist es sowohl falsch die Schuld auf den Treiber zu schieben wie auch falsch nochmal alle 100 bytes zu schicken.
Hier ist z.B. ein schlankes Beispiel in C:
http://stackoverflow.com/questions/1418 ... s-are-sent
Hier ist ein Testschnipsel zum Rumspielen basierend auf berkely Sockets für PB (Linux u. Windows) wo alles in Threads ist (sogar der Test-Client der auch auf 'nem anderem PC laufen könnte) - und mit mit 'nem Switch für Blocking Sockets.
Code: Alles auswählen
EnableExplicit
Structure serverdata
address.s
port.u
blocking.i
EndStructure
Structure clientstuff
socket.i
IP.i
port.u
blocking.i
EndStructure
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
;{
ImportC ""
errno_location() As "__errno_location"
EndImport
#AF_INET = 2
#INADDR_ANY = $00000000
#SOCK_STREAM = 1
#SOL_SOCKET = 1
#SO_REUSEADDR = 2
#SO_RCVTIMEO = 20
#SO_SNDTIMEO = 21
Structure hostent
*h_name
*h_aliases
h_addrtype.l
h_length.l
*h_addr_list
EndStructure
Structure timeval
tv_sec.i
tv_usec.i
EndStructure
Structure sockaddr
sa_family.u
sa_data.b[14]
EndStructure
Structure in_addr
s_addr.l
EndStructure
Structure sockaddr_in
sin_family.u
sin_port.u
sin_addr.l
sin_zero.b[SizeOf(sockaddr)-2-SizeOf(unicode)-SizeOf(in_addr)]
EndStructure
#SOCK_DGRAM = 2
#SO_ERROR = 4
Structure pollfd
fd.l
events.w
revents.w
EndStructure
#POLLIN = $001
#POLLPRI = $002
#POLLOUT = $004
#POLLRDNORM = $040
#POLLRDBAND = $080
#POLLWRNORM = $100
#POLLWRBAND = $200
#POLLERR = $008
#POLLHUP = $010
#POLLNVAL = $020
PrototypeC proto_poll(*fds.pollfd,num.i,timeout.l)
Global libc = OpenLibrary(#PB_Any,"libstdc++.so.6")
If Not libc
libc = OpenLibrary(#PB_Any,"libc.so.6")
EndIf
If Not libc
End 1
EndIf
Global poll.proto_poll = GetFunction(libc,"poll")
If Not poll
End 1
EndIf
;}
CompilerEndIf
Procedure SelectSocket(socket.l,blocking.i=1)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Protected checkin.fd_set
Protected sel_time.timeval
checkin\fd_array[0] = socket
checkin\fd_count = 1
If blocking
ProcedureReturn(select_(socket+1,@checkin,#Null,#Null,#Null))
Else
sel_time\tv_usec = 1
ProcedureReturn(select_(socket+1,@checkin,#Null,#Null,@sel_time))
EndIf
CompilerElse
Protected checkin.pollfd
Protected ret.l
checkin\fd = socket
checkin\events = (#POLLIN|#POLLRDBAND|#POLLERR|#POLLHUP|#POLLNVAL)
If blocking
ret = poll(@checkin,1,-1)
Else
ret = poll(@checkin,1,1)
EndIf
If checkin\revents &(#POLLERR|#POLLHUP|#POLLNVAL)
ret = -1
EndIf
ProcedureReturn(ret)
CompilerEndIf
EndProcedure
Procedure Send(socket.i,*buf,size.l)
Protected tx.l
Protected sent.l
Repeat
sent = send_(socket,*buf+tx,size-tx,0)
If sent = -1
ProcedureReturn(-1)
Else
tx + sent
EndIf
Until tx = size
ProcedureReturn(tx)
EndProcedure
Procedure Close(socket)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
shutdown_(socket,2)
closesocket_(socket)
CompilerElse
Protected con_error.i
Protected con_error_len.i
getsockopt_(socket,#SOL_SOCKET,#SO_ERROR,@con_error,@con_error_len)
shutdown_(socket,2)
close_(socket);
CompilerEndIf
EndProcedure
Procedure SetSocketNonBlocking(socket,val.l)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
ioctlsocket_(socket , #FIONBIO, @val)
CompilerElse
ioctl_(socket, $5421, @val)
CompilerEndIf
EndProcedure
Procedure.s GetError()
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
ProcedureReturn(Str(WSAGetLastError_()))
CompilerElse
ProcedureReturn(PeekS(strerror_(PeekL(errno_location()))))
CompilerEndIf
EndProcedure
Procedure ClientNWThread(*client.clientstuff)
Protected socket_check
Protected incoming_bytes
Protected *rx_buf = AllocateMemory(65536)
If *rx_buf
Repeat
PrintN("Server (Thread for "+IPString(*client\IP)+":"+Str(*client\port)+"): Loop - blocking = "+Str(*client\blocking))
socket_check = SelectSocket(*client\socket,*client\blocking)
If socket_check > 0
incoming_bytes = recv_(*client\socket,*rx_buf,65536,0)
If incoming_bytes > 0
PrintN("Server (Thread for "+IPString(*client\IP)+":"+Str(*client\port)+"): Got "+Str(incoming_bytes)+" bytes from client: "+PeekS(*rx_buf,incoming_bytes))
Send(*client\socket,@"pong",StringByteLength("pong"))
ElseIf incoming_bytes = 0
PrintN("Server (Thread for "+IPString(*client\IP)+":"+Str(*client\port)+"): Client gracefully closed the connection")
Break
Else
PrintN("Server (Thread for "+IPString(*client\IP)+":"+Str(*client\port)+"): Socket error "+GetError())
Break
EndIf
EndIf
ForEver
EndIf
Close(*client\socket)
FreeMemory(*client)
ProcedureReturn(0)
EndProcedure
Procedure ServerNWThread(*server.serverdata)
Protected *host.HOSTENT
Protected srv_sd.l
Protected srv_addr.sockaddr_in
Protected cli_sd.l
Protected cli_addr.sockaddr_in
Protected cli_addr_size.i = SizeOf(cli_addr)
Protected *newclient.clientstuff
Protected onvar.l = 1
*host = gethostbyname_(*server\address.s)
srv_addr\sin_family = #AF_INET
srv_addr\sin_port = htons_(*server\port)
srv_addr\sin_addr = PeekL(PeekL(*host\h_addr_list))
srv_sd = SOCKET_(#AF_INET,#SOCK_STREAM,0)
If Not *server\blocking
SetSocketNonblocking(srv_sd,1)
EndIf
bind_(srv_sd,@srv_addr,SizeOf(srv_addr))
listen_(srv_sd,5)
Repeat
PrintN("Server (Serverthread): Loop - blocking = "+Str(*server\blocking))
cli_sd = accept_(srv_sd,@cli_addr,@cli_addr_size)
If cli_sd > 0
PrintN("Server (Serverthread): New client connected from "+IPString(PeekI(@cli_addr\sin_addr))+":"+Str(ntohs_(cli_addr\sin_port)))
*newclient = AllocateMemory(SizeOf(clientstuff))
If *newclient
*newclient\socket = cli_sd
*newclient\IP = PeekI(@cli_addr\sin_addr)
*newclient\port = ntohs_(cli_addr\sin_port)
*newclient\blocking = *server\blocking
CreateThread(@ClientNWThread(),*newclient)
EndIf
EndIf
If Not *server\blocking
Delay(1)
EndIf
ForEver
EndProcedure
Procedure TestClient(*void)
Protected *host.HOSTENT
Protected sd.l
Protected addr.sockaddr_in
Protected onvar.l = 1
Protected socket_check
Protected incoming_bytes
Protected *rx_buf = AllocateMemory(65536)
*host = gethostbyname_("localhost")
addr\sin_family = #AF_INET
addr\sin_port = htons_(443)
addr\sin_addr = PeekL(PeekL(*host\h_addr_list))
sd = SOCKET_(#AF_INET,#SOCK_STREAM,0)
;SetSocketNonBlocking(socket,onvar.l)
If connect_(sd,@addr,SizeOf(sockaddr_in)) = 0
Send(sd,@"ping",StringByteLength("ping"))
Delay(1000)
Repeat
socket_check = SelectSocket(sd)
If socket_check > 0
incoming_bytes = recv_(sd,*rx_buf,65536,0)
If incoming_bytes > 0
PrintN("Testclient "+Str(*void)+" (this or another PC): Got "+Str(incoming_bytes)+" bytes from server: "+PeekS(*rx_buf,incoming_bytes))
Break
ElseIf incoming_bytes = 0
PrintN("Testclient "+Str(*void)+" (this or another PC): Server gracefully closed the connection")
Break
Else
PrintN("Testclient "+Str(*void)+" (this or another PC): Socket error "+GetError())
Break
EndIf
EndIf
ForEver
Close(sd)
ProcedureReturn(0)
EndIf
EndProcedure
InitNetwork()
OpenConsole()
Define newserver.serverdata
newserver\address = "0.0.0.0"
newserver\port = 443
newserver\blocking = 1 ; Switch to 0 for non-blocking
CreateThread(@ServerNWThread(),@newserver)
Delay(1000)
CreateThread(@TestClient(),1)
CreateThread(@TestClient(),2)
CreateThread(@TestClient(),3)
; Mainthread
Repeat
; Important other server stuff
Delay(1000)
ForEver