0

I am very new to networking and have an issue with sending messages during a while loop.

To my knowledge I should do something along the lines of this:

Create Socket()
Connect()

While
     Do logic
     Send()
End while

Close Socket()

However it sends once and returns -1 there after.

The code will only work when I create the socket in the loop.

While
     Create Socket()
     Connect()
     Do logic
     Send()
     Close Socket()
End while

Here is a section of the code I am using but doesn't work:

//init winsock
WSAStartup(MAKEWORD(2, 0), &wsaData);

//open socket
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    //connect
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family      = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(ipaddress);
    serveraddr.sin_port        = htons((unsigned short) port);
    connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr));

while(true) {

    if (send(sock, request.c_str(), request.length(), 0)< 0 /*!= request.length()*/) {
        OutputDebugString(TEXT("Failed to send."));
    } else {
        OutputDebugString(TEXT("Activity sent."));
    }
    Sleep(30000);
}
//disconnect
closesocket(sock);

//cleanup
WSACleanup();

The function CheckForLastError() returns:10053

WSAECONNABORTED Software caused connection abort. An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error

Thanks

Ryan
  • 1
  • 2
  • 1
    connect should be outside the while loop as well. Could you show the example that you're having issues with? – default Mar 13 '13 at 11:07
  • I wrote an extensive answer about winsock [here](http://stackoverflow.com/a/2920787/238902 "C++ Winsock P2P"). That might be of some assistance? – default Mar 13 '13 at 11:09
  • 1
    The right way is the one in your first example, it sends only once then returns an error. You should call [WSAGetLastError](http://msdn.microsoft.com/en-us/library/windows/desktop/ms741580%28v=vs.85%29.aspx) to get that error, this should give you a hint as to why it is failing. Your second example works only cause you are _repeating_ the first example; create socket, connect, send, close socket, got back to step one. – Karim ElDeeb Mar 13 '13 at 11:27
  • Its going to an internal ipaddress. Would this make any difference? – Ryan Mar 13 '13 at 11:57
  • 1
    is that ip address listening to any traffic? – default Mar 13 '13 at 12:00
  • It just submits a http get request: string request="GET /cron/test.php?username="; request+=username; request+=" HTTP/1.0\r\n"; request+="Host: 172.16.4.29\r\n"; request+="\r\n"; – Ryan Mar 13 '13 at 12:02
  • 1
    have you studied what `WSAECONNABORTED` means? That might give you clues of how to proceed – default Mar 13 '13 at 12:09
  • You can use [WireShark](http://www.wireshark.org/) to check the network traffic of your program. – default Mar 13 '13 at 12:10
  • 2
    Change your last `request+="\r\n";` to `request+="\r\n\r\n";`. [HTTP](http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) needs _double newline_ to end the request, and you are sending only one, so the HTTP server is just waiting for you to _finish_ sending. – Karim ElDeeb Mar 13 '13 at 13:08
  • Unfortunately that didn't seem to fix the problem. It sends the first 4 time ok but then crashes on the 5th. same error. – Ryan Mar 13 '13 at 13:50
  • Are you sure the HTTP server is not closing the connection for inactivity or timeout? What happens if you change `Sleep()` from 30 seconds to something lower? – Karim ElDeeb Mar 14 '13 at 10:10
  • 1
    @Ryan HTTP is a command/response protocol, but the code shown is not reading any of the server's responses, so they are just going to sit in your socket's receive buffer until the socket is closed. If you leave the connection open, that buffer is eventually going to fill up, preventing the server from being able to send any further data, so it may decide to just abort the connection instead. So, if you are going to leave the connection open, you must read what the server sends back for each request, even if you don't care what it says... – Remy Lebeau Sep 17 '21 at 00:18
  • 1
    ... Incidentally, since you are sending an HTTP 1.0 request, the server SHOULD be closing its end of the connection after sending a single response, since HTTP 1.0 did not have keep-alives by default, and you are not explicitly requesting a keep-alive with a `Connection: keep-alive` request header. But your code shown is not handling server-side disconnects, either. – Remy Lebeau Sep 17 '21 at 00:23

2 Answers2

-1

I have been looking for a solution to this problem too. I am having the same problem with my server. When trying to send a response from inside the loop, the client seems never to receive it.

As I understand the problem, according to user207421's suggestions, when you establish a connection between a client and a server, the protocol should have enough information to let the client know when the server has finished sending the response. If you see this example, you have a minimum HTTP server that responds to requests. In this case, you can use a browser or an application like Postman. And if you see the response message, you will see a header called Connection. Setting its value to close tells the client which one is the last message from the server for that request. The message is being sent, but the client keeps waiting, maybe because there is no closing element the client can recognize. I was also missing the Content-Length header. My HTTP response message was wrong, and the client was lost.

This diagram shows what needs to be outside the loop and what needs to be inside.

enter image description here

Timbergus
  • 3,167
  • 2
  • 36
  • 35
  • 1
    It is not necessary to close the connection on every response. It is however necessary for the client not to read until end of stream on every response. Instead both peers need to observe an application protocol under which they can tell where the end of each message is. – user207421 Sep 17 '21 at 00:15
  • That sounds reasonable, but closing the connection when finished, is the only thing that seems to send the message, "that is all I have for you, client!". When visiting the endpoint using a browser, the contents appear on the screen, but the communication remains open, and the browser keeps waiting. Doing the same with a program like Insomnia does not work either. The program keeps waiting forever, showing no answer. Could you test the code attached to the answer for this particular case? Which should be the proper "end of communication" here? – Timbergus Sep 17 '21 at 07:40
  • Still wrong. I already stated your real problem: your client must be reading until end of stream, which never arrives if the server doesn't close after the response. The following are just some well-known protocols that don't close after every response: HTTP, FTP, TLS, RMI, IIOP, SMTP, POP3, IMAP, ... I could go on. I am not here to test code in other people's answers, and neither is anybody else. – user207421 Sep 17 '21 at 08:14
  • NB I glanced at your link. It only contains a server. Not the site of the problem. Closing a socket does not force anything to the other end that wouldn't be sent anyway, except the actual close bit. – user207421 Sep 17 '21 at 08:17
  • I'm sorry, you are right. Checking code shouldn't be anybody's task here. My bad for asking I got the idea of what you are trying to tell me, and I'm going to rewrite the answer I gave. You have helped me a lot, @user207421. Thanks – Timbergus Sep 17 '21 at 09:36
-2

To understand how and why your program fails,you have to understand the functions you use. Some of them are blocking functions and some are them not. Some of them need previous calles of other functions and some of them don't. Now from what i understand we are talking about a client here,not a server. The client has only non blocking functions in this case. That means that whenever you call a function,it will be executed without waiting. So send() will send data the second it is called and the stream will go on to the next line of code. If the information to be sent was not yet ready...you will have a problem,since nothing will be sent. To solve it you could use some sort of a delay. The problem with delays is that they are Blocking functions meaning your stream will stop once it hits the delay. To solve it you can create a thread and lock it untill the information is ready to be sent. But that would do the job for one send(). You will send the info and thats that. If you want to hold the communication and send repeatedly info,you will need to create a while loop. once you have a while loop you dont have to worry about anything. That is because you can verify that the information is ready with a stream control and you can use send over and over again before terminating the connection. Now the question is what is happening on the server side of things? "ipaddress" should hold the ip of the server. The server might reject your request to connect.Or worst he might accept your request but he is listening with diffrent settings in relation to your client.Meaning that maybe the server is not reciving (does not have recv() function)information and you are trying to send info... that might resault in errors/crashes and what not.

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • 1
    "*The client has only non blocking functions in this case*" - `socket()` creates a new socket that operates in blocking mode by default. So `send()` will block until its work is finished. To get the kind of non-blocking behavior you describe, you have to explicitly put the socket into non-blocking mode, using `ioctlsocket(FIONBIO)` for instance. – Remy Lebeau Sep 17 '21 at 00:13