The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Grincheux on March 17, 2011, 06:15:06 AM

Title: Network programming
Post by: Grincheux on March 17, 2011, 06:15:06 AM
I have to write a server and a client programs. Not very difficult for a home only usage.
The goal is that every one form distant computers must be able to connect to the server.
Using DynDns.org I got an IP address and a domaind name.
When connecting to the server the client application must use the 23456 port number.
I modified my router to accept incoming connections on that port and redirect it to my IP address 192.168.0.24

What my program actually does :
It resolves the domain name "grincheux.dyndns.biz" and gets the corresponding IP adress.
When I try to bind the created socket to that IP adress on the 23456 port, I get and error.
Quote;   ********************************************
;   *** Obtention de l'adresse IP du serveur ***
;   ********************************************

                     INVOKE   getaddrinfo,__lpszServerName,NULL,NULL,ADDR _lpResult

                     test   eax,eax
                     jnz      @Error_2

                     push   edi
                     push   esi

                     mov      esi,_lpResult
                     mov      edi,OFFSET ServerAddress
                     mov      ecx,(SIZEOF ServerAddress) / (SIZEOF DWord)
                     rep      movsd

                     mov      eax,ServerAddress.ai_addr
                     mov      eax,(sockaddr_in Ptr [eax]).sin_addr
                     mov      _Service.sin_addr,eax

                     INVOKE   freeaddrinfo,_lpResult

                     mov      edi,OFFSET ServerAddress
                     mov      eax,(addrinfo Ptr [edi]).ai_addr
                     mov      lpSockaddr_Ip,eax
                     mov      _dwIpBufferLength,46

                     INVOKE   WSAAddressToString,lpSockaddr_Ip,(addrinfo Ptr [edi]).ai_addrlen,NULL,ADDR szServerIp,ADDR _dwIpBufferLength

                     INVOKE   wsprintf,ADDR _szTmp,ADDR szFmtResult_01,__lpszServerName,ADDR szServerIp

                     pop      esi
                     pop      edi

                     INVOKE   MessageBox,NULL,ADDR _szTmp,ADDR szInfo,MB_OK or MB_APPLMODAL or MB_ICONINFORMATION

;   ******************************************
;   *** Création du socket pour le serveur ***
;   ******************************************

                     INVOKE   socket,AF_INET,SOCK_STREAM,IPPROTO_TCP

                     test   eax,eax
                     jz      @Error_3

                     mov      hServer,eax

                     mov      _Service.sin_family,AF_INET
                     INVOKE   htons,23456
                     mov      _Service.sin_port,ax

                     INVOKE   bind,hServer,ADDR _Service,SIZEOF sockaddr_in

I created a domain name because it is more easier to connect and I expect my program to be installed on many computers as a server or as a station. Using this, everyone can have his own server name. The fix IP address is used because every day the router changes its IP too. Resolving the domain name always gives the same IP address which can be used to connect to my local computer.

Has anyone any idea to do this ?

Thanks for your help. :boohoo:

Title: Re: Network programming
Post by: Grincheux on March 17, 2011, 06:46:45 AM
In the following code (first post) there is a bug. The line with "INVOKE   freeaddrinfo,_lpResult" must be removed or put later in the source code. But this is not the problem. When binding, I get the following error :

QuoteWSAEADDRNOTAVAIL   10049   Cannot assign requested address.
The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer.
This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer
(for example, address or port 0).

Title: Re: Network programming
Post by: georgek01 on March 17, 2011, 11:33:13 AM
My sever/client app works like a charm so here is my code. I hope it helps.

Server Socket Code

DoSocket proc

; initialize winsock

mov color,00000ffh

mov hSocket,NULL

invoke SetWindowText,statusWin,addr szError

invoke SetStatus,1,0
invoke WSAStartup, 202h,addr wsaData
.if eax != NULL
mov color,00h
invoke WSAGetLastError
invoke SetStatus,101,eax
xor eax, eax
ret
.endif

; create socket

invoke SetStatus,2,0
invoke socket, AF_INET, SOCK_STREAM, 0
.IF eax == INVALID_SOCKET
mov color,00000ffh
invoke WSAGetLastError
invoke SetStatus,201,eax
invoke WSACleanup
xor eax, eax
ret
.else
mov hSocket, eax
.ENDIF

invoke SetStatus,3,0
invoke WSAAsyncSelect,hSocket,hWin,WM_SOCKET,FD_ACCEPT + FD_CONNECT + FD_READ + FD_WRITE + FD_CLOSE
.if eax == SOCKET_ERROR
mov color,00000ffh
invoke WSAGetLastError
invoke SetStatus,301,eax
invoke WSACleanup
xor eax, eax
ret
.endif

; bind and listen

invoke SetStatus,4,0
mov service.sin_family, AF_INET
mov service.sin_addr, INADDR_ANY

mov eax,dwPort
invoke htons, 1024
mov service.sin_port, ax

invoke bind, hSocket, addr service, SIZEOF service
.if eax == SOCKET_ERROR
mov color,00000ffh
invoke WSAGetLastError
invoke SetStatus,401,eax
invoke WSACleanup
xor eax, eax
ret
.endif

invoke SetStatus,5,0
invoke listen,hSocket,10
.if eax == SOCKET_ERROR
mov color,00000ffh
invoke WSAGetLastError
invoke SetStatus,501,eax
invoke WSACleanup
xor eax, eax
ret
.endif

mov color,033d9cdh

invoke SetWindowText,statusWin,addr szIdle

xor eax,eax
Ret
DoSocket EndP


Client Socket Code

DoSocket proc

; initialize winsock

mov hSocket,NULL

invoke SetStatus,1,0
invoke WSAStartup, 101h,addr wsaData
.if eax != NULL
invoke SetStatus,101,0
xor eax, eax
ret
.endif

; create socket

invoke SetStatus,2,0
invoke socket, AF_INET, SOCK_STREAM, 0
.IF eax == INVALID_SOCKET
invoke SetStatus,201,0
invoke WSACleanup
xor eax, eax
ret
.else
mov hSocket, eax
.ENDIF

invoke SetStatus,3,0
invoke WSAAsyncSelect,hSocket,hWin,WM_SOCKET,FD_ACCEPT + FD_CONNECT + FD_READ + FD_WRITE + FD_CLOSE
.if eax == SOCKET_ERROR
invoke SetStatus,301,0
invoke WSACleanup
xor eax, eax
ret
.endif

; connect

mov service.sin_family, AF_INET
invoke htons, 1024                   
mov service.sin_port,ax                   
invoke inet_addr, addr ipAddress    ; convert the IP address into network byte order
mov service.sin_addr,eax

invoke SetStatus,4,0
invoke connect,hSocket,addr service,sizeof service
.if eax == SOCKET_ERROR
invoke WSAGetLastError
.if eax != WSAEWOULDBLOCK       
invoke SetStatus,401,eax
invoke WSACleanup
xor eax, eax
ret
.else
; ready to go
.endif
.endif


xor eax,eax
Ret
DoSocket EndP

Title: Re: Network programming
Post by: drizz on March 17, 2011, 11:53:31 AM
You can't bind socket to router resource ( the address that grincheux.dyndns.biz resolves to ).
Use 0.0.0.0:port with port forwarded to 192.168.0.24 on router should work.
Title: Re: Network programming
Post by: Grincheux on March 17, 2011, 05:52:16 PM
Thanks George, now it works, the only diffrence was
Quotemov service.sin_addr, INADDR_ANY
in the server.. I made this change and know it works... on my pc. I finish the server and the station (FD_CONNECT / FD_READ...) and send it to friends so far that I think that it they connect the problem will be solved. For testing, I will send them a file from my PC.

If I test at home, I think it will be ok, on my pc and on the children's computer. I don't like that kind of test.

Bye & Thanks
Title: Re: Network programming
Post by: Grincheux on March 19, 2011, 07:26:11 AM
QuoteUse 0.0.0.0:port with port forwarded to 192.168.0.24 on router should work

That means that everyone that tries to connect at 0.0.0.0, from everywhere in the world, using port 23456 could connect to my server at 192.168.x.x ?
Title: Re: Network programming
Post by: Grincheux on March 19, 2011, 10:57:50 AM
I think that using MSMQ with such MQCreateQueue functions could help me. I never used it. Does anyone has any sample ont Message Queuing .
Title: Re: Network programming
Post by: Tedd on March 19, 2011, 02:52:04 PM
You need to understand the separation caused by your router.

192.168.x.x is the ip-address INSIDE the safe domain of your network. No-one from the scary outside world (the internet) sees that. Your dyndns ip-address is the only place others can connect to 'you.'

When you open a socket, you make a connection to your router - YOUR ip-address is 192.168.x.x. When the router receives your connection, it forwards that (depending on settings) to the internet (ITS ip-address is the external dyndns one.) When it receives any data for that connection, that is forwarded to you. You are never really connected to the internet.

Your computers only ever have 192.168.x.x ip-addresses. For someone to connect to your computer, they must connect to the router. The router must then forward that connection to you.
To run a server that others can connect to, bind your socket to "0.0.0.0" and then set it to 'listen.' You will also need to set your router to forward connections from the internet on port 23456 to your computer.
Then, when someone connects to "grincheux.dyndns.biz" on port 23456, the router will receive the connection. It will check the rules, and then forward the connection to your computer. Then you can use the received connection as normal (as if it were a direct one.)
Title: Re: Network programming
Post by: Grincheux on March 19, 2011, 02:57:26 PM
Thanks, it seems clearer now.
Title: Re: Network programming
Post by: Grincheux on March 25, 2011, 08:19:35 PM
For Tedd
QuoteSERVER CODE

InitLan                  PROC   __hWnd:HWND,__lpszServerName:LPSTR
                     LOCAL   _WsaData:WSADATA
                     LOCAL   _Service:sockaddr_in
                     LOCAL   _lpHostEnt:Ptr hostent

;   *********************************
;   *** Initialisation de WinSock ***
;   *********************************

                     INVOKE   WSAStartup,202h,ADDR _WsaData

                     test   eax,eax
                     jnz      @Error_1

                     INVOKE   gethostname,ADDR szServerName,SIZEOF szServerName

                     INVOKE   htons,F32_PORT

                     mov      _Service.sin_port,ax
                     mov      _Service.sin_family,AF_INET

;   ********************************************
;   *** Obtention de l'adresse IP du serveur ***
;   ********************************************

                     INVOKE   gethostbyname,ADDR szServerName

                     test   eax,eax
                     jz      @Error_2

                     mov      eax,(hostent Ptr [eax]).h_list
                     mov      eax,DWord Ptr [eax]
                     mov      eax,DWord Ptr [eax]
                     mov      dwServerIpAddress,eax
                     mov      _Service.sin_addr,eax

;   ******************************************
;   *** Création du socket pour le serveur ***
;   ******************************************

                     INVOKE   WSASocket,AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL,WSA_FLAG_OVERLAPPED

                     test   eax,eax
                     jz      @Error_3

                     mov      hServer,eax

                     INVOKE   WSAAsyncSelect,eax,__hWnd,WM_SOCKET,FD_CONNECT or FD_ACCEPT or FD_READ or FD_WRITE or FD_CLOSE or FD_CONNECT

                     INVOKE   bind,hServer,ADDR _Service,SIZEOF sockaddr_in

                     cmp      eax,SOCKET_ERROR
                     je      @Error_5

                     INVOKE   listen,hServer,SOMAXCONN

                     cmp      eax,SOCKET_ERROR
                     je      @Error_6

                     INVOKE   Log,ADDR szLog_0001

@Exit :

                     mov      eax,TRUE
                     ret

;   ****************************************
;   *** Impossible d'initialiser WinSock ***
;   ****************************************

                     ALIGN   16

@Error_1 :

                     mov      edx,OFFSET szError_1
                     jmp      @Error

;   *****************************************************
;   *** Impossible d'obtenir des infos sur le serveur ***
;   *****************************************************

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_2 :

                     mov      edx,OFFSET szError_2
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_3 :

                     mov      edx,OFFSET szError_3
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_4 :

                     mov      edx,OFFSET szError_4
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_5 :

                     call   WSAGetLastError

                     cmp      eax,WSAEWOULDBLOCK
                     je      @Exit

                     mov      edx,OFFSET szError_5
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_6 :

                     mov      edx,OFFSET szError_6
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error :

                     push   MB_OK or MB_APPLMODAL or MB_ICONINFORMATION
                     push   OFFSET szError
                     push   edx
                     push   __hWnd

                     INVOKE   MessageBeep,MB_ICONEXCLAMATION

                     call   MessageBox
                     call   WSACleanup

                     xor      eax,eax
                     ret
InitLan                  ENDP


I don't bind on "0.0.0.0" and it works fine. I can connect from a customer's pc at his home to my pc. The most difficult part is too understand that there is a loopback problem so I can't test the server and the station onto the same computer as I would do for testing a home network.
QuoteSTATION CODE

                     jnz      @Error_1

;   ********************************************
;   *** Obtention de l'adresse IP du station ***
;   ********************************************

                     INVOKE   htons,F32_PORT

                     mov      _Service.sin_port,ax

                     INVOKE   gethostbyname,__lpszServerName

                     test   eax,eax
                     jz      @Error_2

                     mov      eax,(hostent Ptr [eax]).h_list
                     mov      eax,DWord Ptr [eax]
                     mov      eax,DWord Ptr [eax]
                     mov      dwStationIpAddress,eax
                     mov      _Service.sin_addr,eax
                     mov      _Service.sin_family,AF_INET

;   ******************************************
;   *** Création du socket pour la station ***
;   ******************************************

                     INVOKE   WSASocket,AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED

                     test   eax,eax
                     jz      @Error_3

                     mov      hStation,eax

                     INVOKE   wsprintf,_lpszTmp,ADDR szLog_0000,eax
                     INVOKE   Log,_lpszTmp

                     INVOKE   WSAAsyncSelect,hStation,__hWnd,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_READ or FD_WRITE or FD_CLOSE
                     INVOKE   WSAConnect,hStation,ADDR _Service,SIZEOF sockaddr_in,ADDR WsaBuffer_Caller,ADDR WsaBuffer_Callee,NULL,NULL

                     cmp      eax,SOCKET_ERROR
                     je      @Error_5

@Exit :

                     INVOKE   wsprintf,_lpszTmp,ADDR szLog_0001,hStation
                     INVOKE   Log,_lpszTmp

                     mov      eax,TRUE
                     ret

;   ****************************************
;   *** Impossible d'initialiser WinSock ***
;   ****************************************

                     ALIGN   16

@Error_1 :

                     mov      edx,OFFSET szError_1
                     jmp      @Error

;   *****************************************************
;   *** Impossible d'obtenir des infos sur le serveur ***
;   *****************************************************

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_2 :

                     mov      edx,OFFSET szError_2
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_3 :

                     mov      edx,OFFSET szError_3
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_4 :

                     INVOKE   freeaddrinfo,_lpResult

                     mov      edx,OFFSET szError_4
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error_5 :

                     call   WSAGetLastError

                     cmp      eax,WSAEWOULDBLOCK
                     je      @Exit

                     mov      edx,OFFSET szError_5
                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

;@Error_6 :

;                     mov      edx,OFFSET szError_6
;                     jmp      @Error

;-----------------------------------------------------------------
                     ALIGN   16
;-----------------------------------------------------------------

@Error :

                     push   MB_OK or MB_APPLMODAL or MB_ICONINFORMATION
                     push   OFFSET szError
                     push   edx
                     push   __hWnd

                     INVOKE   Log_Errors,edx

                     INVOKE   MessageBeep,MB_ICONEXCLAMATION

                     call   MessageBox
                     call   WSACleanup

                     xor      eax,eax
                     ret
InitLan                  ENDP

"grincheux.dyndns.biz" is the "__lpszServerName" parameter.
Now, I have all the necessary code for building my PC to PC forum.

The only thing I have a problem is for listenning on many ports at the same time. WinSocks permits it when using at least Vista, but generally my members use XP. SO for the moment I don't know how to do.

Thanks for your help.


Title: Re: Network programming
Post by: Tedd on March 26, 2011, 03:02:46 PM
Is there a reason you need to listen on multiple ports? The point of a port is to have a well-defined 'location' to connect to for a given service. Different ports should provide different services - so they should, naturally, have different sockets associated with them.

For multiple users connecting to your service, they all connect to the same port. When a connection is accepted, another NEW socket is created for communication between your server and the connecting client. The original listening socket stays as it was and goes back to listening for future incoming connections. So there is no problem with multiple clients connecting to the 'same' port, because they are still separate connections originating from different ip-addresses (and ports.)

Alternatively, if you really do wish to provide multiple services, via multiple ports, there shouldn't be much issue to continue as you are with WSAAsyncSelect - since you only receive notification upon an event. However, if you're really concerned about efficiency, you can monitor multiple sockets using a call to select. Though this will increase the complexity of the code you have to write, and you will probably have to avoid using WSAAsyncSelect on the same sockets.
Title: Re: Network programming
Post by: Grincheux on March 26, 2011, 03:08:17 PM
I was afraid that my server could not accept all the incoming connections, so I thought that listening on multiple ports could be an answer. In that case I would have to create many listening sockets. But is it the real answer. I will study your las post, I learnt many things with it.

Thanks.
Title: Re: Network programming
Post by: oex on March 26, 2011, 04:55:06 PM
These ports arent 'physical ports' so you can listen to all traffic on one port.... You might have multiple connections with multiple *sockets*.... You would retrieve a header on each initial connection maybe to identify which connection is which and then all data on that socket would be the same user....

ie as an example when you access the web traffic to http:// is generally all port 80 even if you are accessing 2 webpages at the same time in different browser windows....
Title: Re: Network programming
Post by: Grincheux on March 26, 2011, 05:06:02 PM
Listenning on multiple ports could be a solution if I had a large number of users, but I don't think my program will be a facebook like !
I made many tests, the connexion is ok from every place I tried.
Now, i am thinking about sending and receiving datas. I would like to use a thread for sending and an other for receiving. I want to do like this because, I could get two users that transmit nearly at the same time. If the receiving function is not stored into a thread I can't get the second ?
One thing, I am thinking about is how to check that a connection is lost. Do I have to create a timer for sending dummy datas to each connected user ? Do I have to wait that I receive from or I have to send to ?
After I resolve these points there is no problem for the rest of the program.
Thanks for your help.
Title: Re: Network programming
Post by: Tedd on March 26, 2011, 10:48:38 PM
oex, I'm afraid you're only confusing things further ::) You should read this too.


I did explain this point, because I know it's something that's often missed or skipped over. But let's try again..

So, let's assume you have 3 people connecting to your server all at the exact same second. What happens?
All 3 incoming connections are on the same port, and are queued by winsock.
Since you're using WSAAsyncSelect, you receive a notification for the 'first' connection (whichever happens to be randomly queued first - obviously one of them must be.)
Your handler responds to that notification by calling accept for the connection. At this point something magical happens - A NEW SOCKET is created. This is a completely separate and new socket - not the same one used for listening on. Any data you send or receive on that socket is purely between this server and that particular client.
Once you've finished dealing with that, you will inevitably receive yet another incoming connection notification, since there are 2 more connections waiting in the queue. So the same thing happens again - new sockets are created - until the queue is empty.

Now, by the end of this, you have the following: 1 original socket listening on your service port. 1 socket connected to client 1 from some free user port. 1 socket connected to client 2 from another free user port. And yet another socket connected to client 3 from a completely different free user port.
Your listening socket is still listening and ready for any incoming connections. And your other 3 sockets are all connected to their individual clients, separately, without interfering with each other or the listening port. And they all use different outgoing ports for communication, even though they connected to the same incoming port.
Title: Re: Network programming
Post by: Tedd on March 26, 2011, 11:00:55 PM
Quote from: Grincheux on March 26, 2011, 05:06:02 PM
Now, i am thinking about sending and receiving datas. I would like to use a thread for sending and an other for receiving. I want to do like this because, I could get two users that transmit nearly at the same time. If the receiving function is not stored into a thread I can't get the second ?
You will receive FD_READ each time a user sends something, with wParam indicating the particular socket to read this data from (and thus who sent it.) You can then deal with that and return. And then you'll receive more notifications for other incoming data on other sockets. There isn't really a problem with multiple incoming connections, unless you're streaming lots of data and need low latency.

Quote
One thing, I am thinking about is how to check that a connection is lost. Do I have to create a timer for sending dummy datas to each connected user ? Do I have to wait that I receive from or I have to send to ?
You receive FD_CLOSE when a client closes the connection or the connection is lost. You don't need to do anything special (except add it to the mask in WSAAsyncSelect.) When the connection is closed, there is no remaining incoming data to receive.
Title: Re: Network programming
Post by: oex on March 26, 2011, 11:05:05 PM
Quote from: Tedd on March 26, 2011, 10:48:38 PM
oex, I'm afraid you're only confusing things further ::) You should read this too.

Ah sorry, it's a very long time since I wrote any server code :lol
Title: Re: Network programming
Post by: Grincheux on March 27, 2011, 06:48:57 AM
Thank you Tedd, a very good course.

FOr incoming connections now that's ok.

I want to test if the station already is connected, for the following reason. My job, is to repair phone lines. I repair when a tree is falling to the line cable, or when there are too many errors on the customer's line. When there is a lot of wind, the datas can be lost and the link between the router and the head of the line can have a poor quality. There are many technical reasons than make me think that the connection can be lost without receiving a FD_CLOSE event.

Some lines I have to repair have a lot of CRC errors (I use a MC2+ for testing lines) and other erros such as FEC, HEC...

I can also find capacitors that will drop the frequency of ADSL and lead a power connection.

Here are the reasons for which I wanted to send dummy datas between the server and the station.

What do you think about
Title: Re: Network programming
Post by: Grincheux on March 27, 2011, 07:59:24 AM
Here is (http://www.jwb-environmental.com/web2/res.nsf/vlFileURLLookup/MC2Plus+Main+User+Guide+ENG+/$FILE/MC2Plus+Main+User+Guide.pdf) a pdf file giving informations about the MC2+ used for my job. The problems I meet during repairing ADSL user's problems, I want to include them into my programs and it seems to be a good idea for me.
Title: Re: Network programming
Post by: Tedd on March 27, 2011, 12:14:29 PM
Quote from: Grincheux on March 27, 2011, 06:48:57 AM
I want to test if the station already is connected, for the following reason. My job, is to repair phone lines. I repair when a tree is falling to the line cable, or when there are too many errors on the customer's line. When there is a lot of wind, the datas can be lost and the link between the router and the head of the line can have a poor quality. There are many technical reasons than make me think that the connection can be lost without receiving a FD_CLOSE event.

Some lines I have to repair have a lot of CRC errors (I use a MC2+ for testing lines) and other erros such as FEC, HEC...

I can also find capacitors that will drop the frequency of ADSL and lead a power connection.

Here are the reasons for which I wanted to send dummy datas between the server and the station.

What do you think about
For stream-based sockets (TCP), this isn't an issue. The connection is frequently checked for connectivity by sending small packets of data - this is all done automatically, you don't need to do anything. If the connection is lost, this will be detected and you will still receive FD_CLOSE after some time-out period with no reply. Transmission errors are also checked - any packets with an incorrect checksum are re-sent (automatically.)

For datagram sockets (UDP), you don't have this support, so you must do almost everything yourself.
Title: Re: Network programming
Post by: Grincheux on March 27, 2011, 02:56:21 PM
I am happy you are there. All my questions have found a very good answer. Thank you. I did not think that FD_CLOSE was running like this. Now the post can be closed.