I am new to socket programming and i currently facing a problem send/receiving information between my client and server. Currently i am sending "TRN" to my client which is received and handled on my client side but then my program gets stuck. The console prints the [DEBUG] Sent start message. but then it never makes it to the MADE IT HERE 1 message. On the client side when it receives the "TRN" it is handled and an int is sent back to the server which i want to be received however it doesn't make it that far. This is my code breakdown:
/* Send the start message. */
write_client_msg(cli_sockfd, "TRN");
printf("\n[DEBUG] Sent start message.\n");
int place_reveal = 0;
printf("\nMADE IT HERE 1");
place_reveal = recv_int(cli_sockfd);
printf("\nThis is the users results: %d", place_reveal);
/* Writes a message to a client socket. */
void write_client_msg(int cli_sockfd, char * msg)
{
int n = write(cli_sockfd, msg, strlen(msg));
if (n < 0)
error("ERROR writing msg to client socket");
}
/* Reads an int from a client socket. */
int recv_int(int cli_sockfd)
{
printf(" MADE IT HERE 2");
int msg = 0;
int n = read(cli_sockfd, &msg, sizeof(int));
if (n < 0 || n != sizeof(int)) /* Not what we were expecting. Client likely disconnected. */
return -1;
printf("[DEBUG] Received int: %d\n", msg);
return msg;
}
What i have found although is that when i hit Control C to exit the program the console output is this:
^C
MADE IT HERE 1 MADE IT HERE 2
OUCH you hit Ctrl-C?!
Goodbye!
Related
I have a client/server setup communicating over tcp sockets.
Functional wise works very nice except i got an errno 9 , randomly but quite often, when reading the socket on the server side.
According to docs and discussions i could find, errno is raised when read operation is done for a socket which is locally closed.
I'm pretty sure i'm not closing the socket in the reading loop on server side. The socket is closed only by client after message is sent.
Here is the reading loop on server side
void *client_listener_thread(void *args)
{
struct th_params *param = (void *) args;
int sockfd, n, client_pos;
message_t messageR;
char logbuf[256], buf[256];
sockfd = param->socket;
while(1)
{
n = read(sockfd, &messageR, sizeof(message_t));
if (n < 0)
{
sprintf(logbuf, "cmd_thread: ERROR reading from socket errno=%d sock=%d thread=%x", errno, sockfd, (uint32_t)(param->client_listener));
logwts(logbuf);
break;
}
else if(n == 0)
{
sprintf(logbuf, "cmd_thread: socket closed by remote peer 2 %x", (uint32_t)(param->client_listener));
logwts(logbuf);
break;
}
else
{
inet_ntop(AF_INET, &messageR.header.sender_ip, buf, 255);
sprintf(logbuf, "cmd_thread:URC Message: ID = %d sender = %s\n", messageR.header.messageID, buf);
logwts(logbuf);
// process message
switch(messageR.header.messageID)
{
case IDENT_ACK:
...
sprintf(logbuf, "New client registered on socket %d %d / %s:%d", sockfd, client_pos, buf, messageR.header.sender_port);
logwts(logbuf);
break;
...
default:
sprintf(logbuf, "cmd_thread:unprocessed message %d", messageR.header.messageID);
logwts(logbuf);
break;
}
}
}
if(sockfd)
close(sockfd);
pthread_exit(NULL);
}
On client side, it is just open the socket, send the message, close the socket.
When running, on server side, i got "New client registered ..." message for the first read and on the second read i got either the expected "socket closed by remote peer..." message or unexpected "ERROR reading from socket.." with errno = 9
As i said functional has no problem, no message lost, the message is received and processed. I could ignore the error but i'm tring to understand it first.
Thx to strace could find the culprit.
A race condition between threads. One thread was closing the socket while the other thread was still using it. A mutex did the job.
Completely true #Sinic's comment
"... that the descriptor (in this case 5) is getting closed elsewhere..."
I create a server that receive http request and print that request. I can successfully print out http request that I receive without closing that client socket but when I close the client socket, the server print out multiple http request that I already printed out before.
This is my code:
int handleConnection(int sockfd)
{
// sockfd is new_sockfd
char fullReq[MAX_HEADER_SIZE];
receiveReq(sockfd, fullReq);
printf("fullReq in handleConnection\n%s", fullReq);
close(sockfd); // bug occur when I close it
return 0;
}
This is the code of recvReq function:
int receiveReq(int sockfd, char *fullReq)
{
char buffer[1];
memset(buffer, 0, sizeof(buffer));
char *bufferPtr = buffer;
char terminators[] = {'\r', '\n'};
int number_of_requests = 0;
int matchedTerminators = 0;
while(number_of_requests <= MAX_HEADER_SIZE)
{
if(matchedTerminators >= 4)
break;
recv(sockfd, bufferPtr, 1, 0);
strncat(fullReq, bufferPtr, 1);
number_of_requests++;
if(buffer[0] == terminators[0] || buffer[0] == terminators[1])
matchedTerminators++;
else
matchedTerminators = 0;
}
return 0;
}
Output if I didn't close the socket:
fullReq in handleConnection
GET / HTTP/1.1
Output if I close the socket:
fullReq in handleConnection
GET / HTTP/1.1
fullReq in handleConnection
GET / HTTP/1.1
fullReq in handleConnection
GET / HTTP/1.1
more...
You should check for the return code of recv. When the client socket closes, recv is likely to fail (depends on how you open your server's socket), and bufferPtr will remain with the same contents, the last request. You can detect if recv failed, for example because the client socket has closed, by checking if it has returned -1. You can check the man pages for recv on various reasons recv might have failed.
Practicing C network programming: I am writing a simple TCP client-server application that is supposed to send a message (in a separate thread for each client) as a string from a the server to the client and print the message on the client side (latter on this will become a console shop app). I am sending the size of the message first, followed by the message itself using sockets, write() function. Server side:
void answer(void *arg) {
struct thData tdL;
tdL= *((struct thData*)arg);
// Welcome message
char *initMsgToClient;
getInitialMessage(&initMsgToClient);
int len_initMsgToClient = strlen(initMsgToClient);
// Returning message to client
if ( write (tdL.cl, &len_initMsgToClient, sizeof(int)) <= 0 ) {
printf("[Thread %d] ",tdL.idThread);
perror ("[Thread] Error at write(): len_initMsgToClient to client.\n");
}
if (write (tdL.cl, initMsgToClient, len_initMsgToClient) <= 0) {
printf("[Thread %d] ",tdL.idThread);
perror ("[Thread]Error at write(): initMsgToClient to client.\n");
}
else
printf ("[Thread %d] Message was sent with success.\n",tdL.idThread);
}
void getInitialMessage(char **paramMessage) {
char *resultMessage = "Welcome to Console Shopper!";
*paramMessage = resultMessage;
}
And on the client side I am reading the size first and the message itself and printing it, but every time I run ./client I get different random trailing characters to the message. Client side:
char welcomeMessageFromServer[512];
int lenWelcomeMsg;
// Reading size of first mesage: lenWelcomeMsg
if (read(sd, &lenWelcomeMsg, sizeof(int)) < 0) {
perror ("[client] Error reading len welcome message from server.\n");
}
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
printf("%s",welcomeMessageFromServer);
printf("\n");
For simplicity, I omitted to add the code for sockets and threads handling, most of it is from a tutorial so it should be correct. I am pretty sure I am doing something wrong with the size of the message that is being sent/received.
My output with multiple runs for ./client:
Welcome to Console Shopper!
Welcome to Console Shopper!�
Welcome to Console Shopper!������i0
Welcome to Console Shopper!������UF+:
Some of the times it gets it right. What should I correct in order to get the right message all the times?
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
printf("%s",welcomeMessageFromServer);
You have two issues here:
The %s format specifier is only for C-style strings. To make your received message a C-style string, you need to put a terminating zero byte on the end of it.
The read function does not ensure that it receives all the bytes requested. You need to check the return value and call it again if you didn't get the whole message.
Try a function like this:
ssize_t readAll (int fd, void *vbuf, size_t count)
{
char *buf = (char *) vbuf;
ssize_t read_so_far = 0;
while (count > 0)
{
ssize_t ret = read(fd, buf, count);
if (ret < 0)
return ret;
if (ret == 0)
return read_so_far;
count -= ret;
read_so_far += ret;
buf += ret;
}
return read_so_far;
}
Then you can do this:
// Reading initial message from server: welcomeMessageFromServer
if (readAll(sd, welcomeMessageFromServer, lenWelcomeMsg) != lenWelcomeMsg) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
welcoemMessageFromServer[lenWelcomeMsg] = 0;
printf("%s",welcomeMessageFromServer);
I'm new to signals, I'm trying to set SIGALRM on UDP echo service, as a socket programming practice.
So here I have a UDP socket, the client sends a string to server and waits for response (any response, here the string is echoed by server).
The goals is to set SIGALRM and let the client resend the string a few times if no responses were made by server or UDP packets get lost.
Here, I used a small sample and simplified long lines with ..., you can get more details on my github repo (line 51)
sigALRM-Client.c
unsigned int tries = 0;
void CatchAlarm()
{
tries += 1;
}
int main(int argc, char **argv)
{
// SKIPPED
// ...
struct sigaction handler;
handler.sa_handler = CatchAlarm;
handler.sa_flags = 0;
if(sigfillset(&handler.sa_mask) < 0)
return 1;
if(sigaction(SIGALRM, &handler, 0) < 0)
return 2;
ssize_t bytes;
bytes = sendto(servSock,...);
while((bytes = recvfrom(servSock,...)) < 0) {
// alarm went off
if(errno == EINTR) {
// try 5 times
if(tries < 5) {
bytes = sendto(servSock,...);
} else {
fprintf(stdout, "no response, waiting...\n");
}
} else {
fprintf(stdout, "failed to get data\n");
return 3;
}
}
// recvfrom() got something, cancel timeout
alarm(0);
fprintf(stdout, "received %d bytes of data\n", bytes);
close(servSock);
}
When I run the client, it won't receive SIGALRM signal and UDP packets get lost in first attempt?!
Client won't retry sending string then exit after 5 attempts, instead, it waits for server response forever!
What prevents client to get SIGALRM?
Did I miss something here?
Your code in the GitHub repo never calls alarm() with a non-zero number. You'll never get an alarm signal delivered automatically unless you actually request one. Relying on some other process to send your process an alarm signal isn't resilient.
I have a client server program in C. Client send the command while server receives it.
But if client shutdown by pressing Ctrl+C the server application process the previous input.
Example.
CLient.c Server.c
-------------------------------------------------
Enter COmmand: adf Command from client: adf
Enter COmmand: bbb Command from client: bbb
Enter Command: Ctrl+c Command from client: bb
I don't understand why it process the previous input.
Given below is my main logic.
main(){
// bind, listen, accept is done.
while(!done && !shutFlag){ // Main server command Loop
done = ReceiveRequestMessage(&request, connectedSock );
if(done)
{
printf("Client closed the connection while recv() \n");
printf("Listening for new client connection to establish... \n");
connectedSock = accept(srvSock, (struct sockaddr *)&connectSAddr, &addrLen );
printf("GetLastError: %d\n", GetLastError());
done = FALSE;
continue;
}
request.record[strlen(request.record)] ='\0';
commandLen = strcspn(request.record, "\n\t");
memcpy(sysCommand, request.record, commandLen);
sysCommand[commandLen] = '\0';
printf("Request recieved from client: %s -> Hex: %X\n\n", request.record, *(request.record));
}
}
ReceiveRequestMessage Function:
static BOOL ReceiveRequestMessage(REQUEST *pRequest, SOCKET sd){
LONG32 nRemainRecv = 0, nRecv;
LPBYTE pBuffer;
BOOL disconnect = FALSE;
nRemainRecv = RQ_HEADER_LEN;
pBuffer = (LPBYTE) pRequest;
while(nRemainRecv > 0 && !disconnect )
{
nRecv = recv (sd, pBuffer, nRemainRecv, 0); // Reading the 1st 4 bytes(length of record)to pRequest.
if ( nRecv > 0 )
printf("Bytes received in request.rqLen: %d\n", nRecv);
else if ( nRecv == SOCKET_ERROR ){
printf("Connection closed\n");
return TRUE;
}
disconnect = (nRecv == 0); // check connection is closed
nRemainRecv -= nRecv;
pBuffer += nRecv;
}
/* Read the request record */
nRemainRecv = pRequest->rqLen;
/* Exclude buffer overflow */
nRemainRecv = min(nRemainRecv, MAX_RQRS_LEN);
pBuffer = (LPSTR)pRequest->record;
while(nRemainRecv > 0 && !disconnect)
{
nRecv = recv(sd, pBuffer, nRemainRecv, 0);
if(nRecv > 0)
printf("Bytes Received in request.record: %d\n", nRecv);
else if(nRecv == SOCKET_ERROR){
printf("Connection closed");
return TRUE;
}
disconnect = (nRecv == 0); // check connection is closed
nRemainRecv -= nRecv;
pBuffer += nRecv;
}
return disconnect;
}
How can I eliminate the last print statement after clicking Ctrl+C in client?
Means:
Whenever Client disconnects by clicking Ctrl+C or in any way. How can I notify Server?
Function ReceiveRequestMessage() returns the value of its variable disconnect.
That variable is set nonzero only if recv() returns 0.
The documentation for recv() promises a return value of 0 only for the case that the remote end performs an orderly shutdown (and no more data are available to receive). It will definitely return -1, not 0, if an error occurs.
It is not safe to assume that the client will perform an orderly shutdown every time it effectively disconnects, and in particular, it is not safe to assume that it will perform one when it is killed by a signal, as happens when you send it a Ctrl+c.
If ReceiveRequestMessage() returns 0 without modifying the object pointed to by its pRequest parameter, then it will appear to the caller that the previously-sent request was repeated. This is what you are observing.