How to push (i.e. flush) data sent to a TCP stream - c

RFC 793 says that TCP defines a "push" function that ensures that the receiver got the data:
Sometimes users need to be sure that all the data they have
submitted to the TCP has been transmitted. For this purpose a push
function is defined. To assure that data submitted to a TCP is
actually transmitted the sending user indicates that it should be
pushed through to the receiving user. A push causes the TCPs to
promptly forward and deliver data up to that point to the receiver.
However, I can't find a push system call. Using fsync on the file descriptor produces an invalid argument error.
I conducted an experiment with a simple server that accepts a connection from a client, waits, then sends 26 bytes to the client:
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 1234
int main(void)
{
int server_fd;
int client_fd;
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
perror("bind");
return 1;
}
}
if (listen(server_fd, 20) != 0) {
perror("listen");
return 1;
}
{
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
printf("Waiting for connection on port %d\n", PORT);
if ((client_fd = accept(server_fd, (struct sockaddr*)&addr, &addrlen)) < 0) {
perror("accept");
return 1;
}
printf("%s:%d connected\n",
inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
}
printf("Giving client time to close connection.\n");
sleep(10);
{
ssize_t sent_length;
if ((sent_length =
send(client_fd, "abcdefghijklmnopqrstuvwxyz", 26, 0)) < 0)
{
perror("send");
return 1;
}
printf("Sent %Zd bytes.\n", sent_length);
}
printf("Closing connection to client\n");
if (close(client_fd) != 0) {
perror("close(client_fd)");
return 1;
}
printf("Shutting down\n");
if (close(server_fd) != 0) {
perror("server: close(server_fd)");
return 1;
}
printf("Done!\n");
return 0;
}
I found that the send call immediately returns 26, even after I close the connection client-side or unplug the network cable. In the latter case, the data appears on the client when I plug the cable back in and wait a few seconds (long after the server has shut down).
How do I ensure that data sent with send is received and acknowledged?

There is no push, says the late W. Richard Stevens; the standard sockets API doesn't provide it, and is not required to do so by RFC 1122. You can set the TCP_NODELAY option, but that's only a partial solution.
If you want to be sure the other end got your data, then let it send an acknowledgment over the TCP channel.

try to add a shutdown call before the close of the socket;
shutdown(client_fd,SHUT_RDWR);
However the real solution is to get an acknowledgement back from the client that it has received the data -- I.e. you need to define a protocol -- the simplest of simple protocols is that the client is responsible for closing the socket when the data is received.

Well as per my limited knowledge, TCP will insure that the data is transferred to the other machine / socket.
But has the program at the other end read / accessed the data cannot be confirmed using standard socket API's. Your other end (client in this case) might be busy doing something else instead of waiting for data to show up.
I think that your requirement will be full filled if you implement some sort of handshaking between server / client to track what all has been received using some kind of acknowledgements.
The acknowledgement mechanism is important if your application depends on it.

You can force immediately sending of small packets by disabling Nagle's algorithm, but this does not guarantee that the client will receive it.
If you have to wait for the acknowledge you have to build this into the protocol and wait for the client to write something into the socket that signals the reception of message.

The only way to make sure your data is send over is to Receive an answer. After testing for many days this is the only way to make sure it is 'flushed' to the other side.
// Receive until the peer closes the connection to make sure all data has been send
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0){
printf("Bytes received: %d\n", iResult);
}
else if (iResult == 0){
printf("Connection closed\n");
}
else{
printf("recv failed with error: %d\n", WSAGetLastError());
}
} while (iResult > 0);

Related

Trying to get started with winsock in C, how to keep connected?

I'm a beginner and trying to set up a TCP-client for the first time, using winsock. I put together a minimal client using some bits of code I found in examples (see below). It's basically working, i.e. I can receive the server's messages, and sending messages gives the expected results.
However, unless I add a loop which constantly does a receive/send routine (or even just the receive part) the connection is closed immediately after it has been established. Can I do something to keep the connection open and only receive or send something when there is demand for it?
The server is a closed source piece of software, so I have no idea about how it is set up.
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
int startWinsock(void) {
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 2), &wsa);
}
int main(void) {
long rc;
SOCKET s;
SOCKADDR_IN addr;
printf("Starting Winsock... ");
rc = startWinsock();
if (rc != 0) {
printf("Error: unable to start Winsock, error code: %d\n", rc);
}
else {
printf("done.\n");
}
printf("Creating socket... ");
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
printf("Error: Unable to create socket, error code: %d\n", WSAGetLastError());
}
else {
printf("done.\n");
}
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(10134);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
if (rc == SOCKET_ERROR) {
printf("Connection failed, error code: %d\n", WSAGetLastError());
}
else {
printf("Connected to 127.0.0.1.\n");
}
//if I add a loop here, which receives and/or sends stuff constantly, the connection stays established
return 0;
}
Very simple:
Your client tries to connect to the server.
If it succeeds, send a command, and read the response.
Keep receiving and sending until you're "done", then close the socket.
In other words:
You have control over when to close the connection - the socket will stay open until you close it.
Essentially, you're inventing your own custom network protocol
STRONG SUGGESTION:
Review Beej's Guide to Network Programming

Sender/receiver behavior when receiver responds in network programming with broadcast

I am learning about broadcasting in network programming (using C). From what I understand, a sender sends a message to all the receivers (who are listening) in the local area network. Using my local machine with a virtual machine I wrote a small program to see how things work.
Code for receiver.c (I put this code on my local machine):
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/unistd.h>
#define PORT 4242
int main() {
int socket_fd, sender_size;
struct sockaddr_in receiver, sender;
char receive_buff[256], send_buff[256];
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) {
perror("failed to create socket");
return -1;
}
int broadcast_yes = 1, reuse_yes = 1;
if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, (void*) &broadcast_yes, sizeof(broadcast_yes)) < 0) {
perror("failed to set broadcast socket option");
return -2;
}
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*) &reuse_yes, sizeof(reuse_yes)) < 0) {
perror("failed to set reuse socket option");
return -3;
}
memset(&receiver, 0, sizeof(receiver));
receiver.sin_family = AF_INET;
receiver.sin_port = htons(PORT);
receiver.sin_addr.s_addr = INADDR_ANY;
if (bind(socket_fd, (struct sockaddr*) &receiver, sizeof(receiver)) < 0) {
perror("failed to bind");
return -4;
}
printf("Listening...\n");
memset(receive_buff, 0, sizeof(receive_buff));
sender_size = sizeof(sender);
if (recvfrom(socket_fd, (void*)receive_buff, sizeof(receive_buff), 0, (struct sockaddr*) &sender, &sender_size) < 0) {
perror("failed to receive broadcast message");
return -5;
}
printf("%s\n", receive_buff);
strcpy(send_buff, "got your message");
if (sendto(socket_fd, (void*)send_buff, sizeof(send_buff), 0, (struct sockaddr*) &sender, sizeof(sender)) < 0) {
perror("failed to send confirmation message");
return -6;
}
close(socket_fd);
return 0;
}
Code for sender.c (I put this code on my virtual machine):
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 4242
int main() {
int socket_fd;
struct sockaddr_in receiver;
char send_buff[256], receive_buff[256];
socklen_t receiver_size;
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) {
perror("failed to create socket");
return -1;
}
int broadcast_yes = 1;
if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, (void*) &broadcast_yes, sizeof(broadcast_yes)) < 0) {
perror("failed to set broadcast socket option");
return -2;
}
memset(&receiver, 0, sizeof(receiver));
receiver.sin_family = AF_INET;
receiver.sin_port = htons(PORT);
receiver.sin_addr.s_addr = inet_addr("192.168.1.255");
strcpy(send_buff, "i'm sending a broadcast message");
if (sendto(socket_fd, (void*)send_buff, strlen(send_buff) + 1, 0, (struct sockaddr*) &receiver, sizeof(receiver)) < 0) {
perror("failed to send broadcast message");
return -3;
}
memset(receive_buff, 0, sizeof(receive_buff));
receiver_size = sizeof(receiver);
if (recvfrom(socket_fd, (void*)receive_buff, sizeof(receive_buff), 0, (struct sockaddr*) &receiver, &receiver_size) < 0) {
perror("failed to receive confirmation message");
return -4;
}
printf("%s\n", receive_buff);
close(socket_fd);
return 0;
}
As you can see, there is nothing fancy. The sender sends the message i'm sending a broadcast message as a broadcast message (since I put 255 at the end of the IPv4 address and I also set the SO_BROADCAST option in the socket). In turn, the receiver waits and receives this message. It also has that SO_BROADCAST option enabled in the socket. What happens afterwards is what is confusing to me. As you can see above after the receiver receives the message, it sends a confirmation message got your message back to the sender.
But what if a sender sends the message to all receivers (listeners) in the LAN and there are MULTIPLE receivers in the LAN, how would this work? Wouldn't EACH of the multiple receivers send that got your message confirmation message to the sender? So it would be like multiple machines have that code in receiver.c and each of these machine would get the sender's address information in the variable struct sockaddr_in sender when the code calls the function recvfrom(). Then, ALL of these machines will send that message got your message to the sender. But the sender has only one recvfrom() function call so it will receive only the first message which arrives to it. The confirmation messages of the other receivers will be lost. Or at least that's what I think is going to happen. How can I solve this and get all the confirmation messages? Again, this question only applies if my understanding of what happens that I stated above is true, which I don't know if it is so I would also ask you if I am correct in thinking that the sender will only receive one confirmation message.
Your understanding is correct.
If you broadcast a message and multiple instances of the receiver get it, each of the will send a response back to the sender.
This means that the sender needs to call recvfrom in a loop to receive multiple messages. But at the same time you don't want the sender to wait forever since you don't know how many responses you'll get.
The simplest way to handle this is to use the select function to check if there's data to read. You can give this function a timeout so you can control how long it waits. If it returns a positive value, there's data to read and you can call recvfrom to read a response, then call select again to wait for more. If it returns 0, then it timed out waiting for a response.

How to handle TCP client disconnect in C

I am trying to write a basic TCP server that streams serial data to a client. The server would connect to a serial device, read data from said device, and then transmit it as a byte stream to the client. Writing the TCP server is no problem. The issue is that the server will crash when a client disconnects. In other languages, like Python, I can simply wrap the write() statement in a try-catch block. The program will try to write to the socket, but if the client has disconnected then an exception will be thrown. In another project, this code snippet worked for me:
try:
client_socket.send(bytes(buf, encoding='utf8'))
except Exception as e:
logger.info("Client disconnected: %s", client_id)
I can handle client disconnects in my C code, but only by first reading from the socket and checking if the read is equal to 0. If it is, then my client has disconnected and I can carry on as usual. The problem with this solution is that my client has to ping back to the server after every write, which is less than ideal.
Does anyone know how to gracefully handle TCP client disconnects in C? My example code is shown below. Thank you!
// Define a TCP socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// Allow for the backlog of 100 connections to the socket
int backlog = 100;
// Supply a port to bind the TCP server to
short port = 9527;
// Set up server attributes
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
// Set the socket so that we can bind to the same port when we exit the program
int flag = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
perror("setsockopt fail");
}
// Bind the socket to the specified port
int res = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (res < 0) {
perror("bind fail");
exit(1);
}
// Listen for incoming connections
if (listen(sockfd, backlog) == -1) {
perror("listen fail");
exit(1);
} else {
printf("Server listening on port\n", port);
}
for(;;) {
// Wait for incoming connection
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
int connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
if (-1 == connfd) {
perror("Could not accept incoming client");
continue;
}
//Resolving Client Address
char buff[INET_ADDRSTRLEN + 1] = {0};
inet_ntop(AF_INET, &cliaddr.sin_addr, buff, INET_ADDRSTRLEN);
uint16_t cli_port = ntohs(cliaddr.sin_port);
printf("connection from %s, port %d\n", buff, cli_port);
for(;;) {
// Read from serial device into variable here, then send
if(send(connfd, "Data...Data...Data\n", 19, 0) < 0) {
printf("Client disconnected...\n");
break;
}
}
}
Looks like a duplicate of this, this and this.
Long story short you can't detect the disconnection until you perform some write (or read) on that connection. More exactly, even if it seems there is no error returned by send, this is not a guarantee that this operation was really sent and received by the client. The reason is that the socket operations are buffered and the payload of send is just queued so that the kernel will dispatch it later on.
Depending on the context, the requirements and the assumptions you can do something more.
For example, if you are under the hypothesys that you will send periodic message at constant frequency, you can use select and a timeout approach to detect an anomaly.
In other words if you have not received anything in the last 3 minutes you assume that there is an issue.
As you can easily found, this and this are a good read on the topic.
Look at that for a far more detailed explanation and other ideas.
What you call the ping (intended as a message that is sent for every received packet) is more similar to what is usually known as an ACK.
You only need something like that (ACK/NACK) if you also want to be sure that the client received and processed that message.
Thanks to #emmanuaf, this is the solution that fits my project criteria. The thing that I was missing was the MSG_NOSIGNAL flag, referenced here.
I use Mashpoe's C Vector Library to create a new vector, which will hold all of my incoming client connections.
int* client_array = vector_create();
I then spawn a pthread that continually reads from a serial device, stores that data in a variable, and then sends it to each client in the client list
void* serve_clients(int *vargp) {
for(;;) {
// Perform a microsleep
sleep(0.1);
// Read from the Serial device
// Get the size of the client array vector
int client_vector_size = vector_size(vargp);
for(int i = 0 ; i < client_vector_size ; i++) {
// Make a reference to the socket
int* conn_fd = &vargp[i];
/*
In order to properly handle client disconnects, we supply a MSG_NOSIGNAL
flag to the send() call. That way, if the client disconnects, we will
be able to detect this, and properly remove them from the client list.
Referenced from: https://beej.us/guide/bgnet/html//index.html#sendman
*/
if (send(*conn_fd, "Reply from server\n", 18, MSG_NOSIGNAL) < 0) {
printf("Client disconnected...\n");
// Close the client connection
close(*conn_fd);
// Remove client socket from the vector
vector_remove(vargp, i);
// Decrement index and client_server_size by 1
i--;
client_vector_size--;
}
}
}
}
To spawn the pthread:
// Spawn the thread that serves clients
pthread_t serving_thread;
pthread_create(&serving_thread, NULL, serve_clients, client_array);
When a new connection comes in, I simply add the new connection to the client vector
while(1) {
// Wait for incoming connection
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
int connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
if (-1 == connfd) {
perror("Could not accept incoming client");
continue;
}
//Resolving Client Address
char buff[INET_ADDRSTRLEN + 1] = {0};
inet_ntop(AF_INET, &cliaddr.sin_addr, buff, INET_ADDRSTRLEN);
uint16_t cli_port = ntohs(cliaddr.sin_port);
printf("connection from %s:%d -- Connfd: %d\n", buff, cli_port, connfd);
// Add client to vector list
vector_add(&client_array, connfd);
}
In the end, we have a TCP server that can multiplex data to many clients, and handle when those clients disconnect.

What is the diffrence between a concurrent tcp client server program and an iterative one?

I want to learn how to write a concurrent TCP client server in C but I can't understand the diffrence between an iterative server-client programm and a concurrent one. On the internet I could not find much information. I look over the TCP client server implementation in C from the site www.geeksforgeeks.org but I think this is an iterative example. How could I make it concurrent?
TCP Server:
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
// Function designed for chat between client and server.
void func(int sockfd)
{
char buff[MAX];
int n;
// infinite loop for chat
for (;;) {
bzero(buff, MAX);
// read the message from client and copy it in buffer
read(sockfd, buff, sizeof(buff));
// print buffer which contains the client contents
printf("From client: %s\t To client : ", buff);
bzero(buff, MAX);
n = 0;
// copy server message in the buffer
while ((buff[n++] = getchar()) != '\n')
;
// and send that buffer to client
write(sockfd, buff, sizeof(buff));
// if msg contains "Exit" then server exit and chat ended.
if (strncmp("exit", buff, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
// Function for chatting between client and server
func(connfd);
// After chatting close the socket
close(sockfd);
}
TCP Client:
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
int n;
for (;;) {
bzero(buff, sizeof(buff));
printf("Enter the string : ");
n = 0;
while ((buff[n++] = getchar()) != '\n')
;
write(sockfd, buff, sizeof(buff));
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server : %s", buff);
if ((strncmp(buff, "exit", 4)) == 0) {
printf("Client Exit...\n");
break;
}
}
}
int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
func(sockfd);
// close the socket
close(sockfd);
}
As stated in the comments, an iterative server will treat each connection sequentially. In your posted example, if you run the server(after ignoring a bunch of warnings), you can only connect one client. A second client will successfully connect the server, but the server will never respond to it. Only the first client will send messages and get responses.
A concurrent implementation would treat both clients in parallel and would be able to get messages from both. I can think of 3 ways to do this, but one is not recommended:
As suggested in the comments, put the accept call in a loop. It will block until someone connects. When someone connects, you spawn a thread and give it all the information you need to communicate with the client, the file descriptor(sockfd) should suffice for a simple example. After that the thread could execute your func, for this thread will only know of one client, but the main loop will block of accept again, waiting for another connection. I found this example on google.
Using POSIX system call select(or it's alternatives poll and epoll), you can monitor a list of sockets for activity. If any of the monitored sockets has activity, a read or accept to it won`t block, and then you treat these sockets. If the server file descriptor has activity, it means a new client connected, you should store the client file descriptor somewhere, and start passing it to select as well. If a client file descriptor has activity, you handle their messages like before. This way requires no thread, everything is handled on the main routine and may have advantages depending on your use-case
I found these two examples on google: here and here
This way is not recommended: Make your server socket non-blocking with fcntl. This way, accept won't block, instead, it will immediately return signaling an error EAGAIN or EWOULDBLOCK. You can then repeatedly call accept on your main loop, most times it will return an error, but the ones that do not will signal a new client connected. When a client connects, you make its file descriptor non-blocking as well, and store it somewhere. On your main routine, for each client socket you will try a read on them, but if no new information is available, it returns an error as well. If something is available, you treat it like before. This has the disadvantage of always demanding 100% CPU utilization. You can insert a delay on the loop, but it will increase additional unnecessary latency. You should not do this.

Recover Socket after restoring a snapshot

I have to following problem. Maybe someone could help me with that.
What I want do achieve is that a service inside a virtual machine (using
virtualbox/WinXP) should send data to the host via socket (client)(1). The host
(socketserver) then takes a snapshot of the current system(2), sends an ack(3) into
the vm (again via socket), that every action was taken and that the service
can continue(4).
Service Host
========= =======
Service sends specific data (1)
---------------------------------------->
Invoke Snapshot (2)
| On restore socket gets destroyed (X) |
| No ACK can be accepted -- Endless Loop| Send ACK (3)
<----------------------------------------
Accept ACK and continue (4)
The Problem occurs, when I restore the vm to a state, which was taken earlier.
The software waits for the ack to continue. The vm takes some time to restore
its network (3-5 seconds until "your network cable is now plugged in..." in
the tray) and this crashes the sockets (X).
I don't have a workaround for that. The Service is written in C. Host is a
python script. Sleep is the worst solution in my opinion. Due to high load,
the time until something happens is not predictable.
I cannot come up with a great idea on how to solve that problem. Would be
great if you could help me.
Thanks in advance!
EDIT:
#alk: I made the assumption, because the client is not connected to server anymore (different states due to restore, and losing the connection for a while I guess)
Here is the C Code from the Service. I hooked certain syscalls, and the code gets executed when a syscall is called
#include <stdio.h>
#include <winsock2.h>
#include <stdarg.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char buffer[1024];
char ack[1024];
int recv_size;
int mpex_send(const char *str, ...)
{
// Build String
va_list va;
va_start(va, str);
vsnprintf(buffer, sizeof(buffer), str, va);
va_end(va);
// Init
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_addr.s_addr = inet_addr("192.168.56.1");
server.sin_family = AF_INET;
server.sin_port = htons( 42000 );
//Connect to remote server
if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");
//Send some data
if( send(s , buffer , strlen(buffer) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
//Receive a reply from the server
while(1)
{
if((recv_size = recv(s , ack , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
ack[recv_size] = '\0';
puts(ack);
// Important, put \n after ack
if (strcmp("ack\n", ack) == 0)
{
puts("Got it");
break;
}
}
closesocket(s);
WSACleanup();
return 0;
}
I managed to solve my problem. Maybe someday will encounter the same, so hopefully this helps.
After the first message from the C code is sent, it will go into a loop state where it tries to create and open a socket (see source above). If they succeed they break; the loop. After that I loop a socket.recv to get the ack from the host.
In this state the host got the message and falls into an ack flooding state, where it sends an ack to all connected clients. So the message is sent to the new connections as well as to the broken ones.
After the C code received the ack, it sends an ack_ack to the host to stop flooding.
This page was very helpful for the python server part.
http://www.binarytides.com/code-chat-application-server-client-sockets-python/
Hope this helps

Resources