Related
I am writing a TCP client and server protocol for a school project. The client sends a "GET \r\n" message and the server has to transfer "+OK\r\n", size of the file and the file, in case it exists in the server directory. I'm blocked in the file transfer
I tried to solve it at small steps at a time. I set up the connection, sent the request from the client and received the "OK" message from the server.
Now I opened the file in the server and tried to send it 128 bytes at a time to the client. The reading of the file works and apparently also the sending of the buffers but the client is not receiving anything...
Here's my server.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 128 /* Buffer length */
#define TIMEOUT 15 /* TIMEOUT */
/* FUNCTION PROTOTYPES */
void service(int s);
/* GLOBAL VARIABLES */
char *prog_name;
int main(int argc, char *argv[])
{
int conn_request_skt; /* passive socket */
uint16_t lport_n, lport_h; /* port used by server (net/host ord.) */
int bklog = 2; /* listen backlog */
int s; /* connected socket */
fd_set cset; // waiting for connection
struct timeval tval; // timeout
size_t n;
socklen_t addrlen;
struct sockaddr_in saddr, caddr; /* server and client addresses */
prog_name = argv[0];
if (argc != 2) {
printf("Usage: %s <port number>\n", prog_name);
exit(1);
}
/* get server port number */
if (sscanf(argv[1], "%" SCNu16, &lport_h)!=1)
err_sys("Invalid port number");
lport_n = htons(lport_h);
/* create the socket */
printf("creating socket...\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done, socket number %u\n",s);
/* bind the socket to any local IP address */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = lport_n;
saddr.sin_addr.s_addr = INADDR_ANY;
showAddr("Binding to address", &saddr);
Bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
/* listen */
printf ("Listening at socket %d with backlog = %d \n",s,bklog);
Listen(s, bklog);
printf("done.\n");
conn_request_skt = s;
/* main server loop */
for ( ; ; )
{
printf("waiting for connection...\n");
/* accept next connection */
FD_ZERO(&cset);
FD_SET(conn_request_skt, &cset);
tval.tv_sec = TIMEOUT;
tval.tv_usec = 0;
n = Select(FD_SETSIZE, &cset, NULL, NULL, &tval);
if ( n > 0 ){
addrlen = sizeof(struct sockaddr_in);
s = Accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
showAddr("Accepted connection from", &caddr);
printf("new socket: %u\n",s);
/* serve the client on socket s */
service(s);
} else {
printf("No connection request after %d seconds\n",TIMEOUT);
}
}
}
void service(int s) {
char buf[BUFLEN]; /* reception buffer */
char filename[BUFLEN];
int n;
long filesize;
uint32_t fsize;
FILE *fp;
for ( ; ; )
{
n = recv(s, buf, BUFLEN, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("Received request from socket %03d :\n", s);
sscanf(buf, "GET %s\r\n", filename);
strcpy(buf, "+OK\r\n");
printf("%s",buf);
if(writen(s, buf, strlen(buf)) != strlen(buf))
printf("Write error while sending +OK\n");
// open file
fp = fopen(filename, "r");
if( fp == NULL){
//TODO close connection
}
// calculating dim of file
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
rewind(fp); // go back at beginning of file
fsize = htonl(filesize); // size file in network byte order
// sending file size
if(writen(s, &fsize, 4) != 4)
printf("Write error while sending file size\n");
while(fread(buf, 1, BUFLEN - 1, fp) == BUFLEN - 1){
printf("%s", buf);
if(writen(s, buf, strlen(buf)) != strlen(buf))
printf("Write error while buf\n");
}
printf("%s", buf);
printf("I am here\n");
}
}
}
While here is my client.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 128 /* BUFFER LENGTH */
#define TIMEOUT 15 /* TIMEOUT*/
/* GLOBAL VARIABLES */
char *prog_name;
int main(int argc, char *argv[])
{
char request[BUFLEN]; /* request buffer */
char rbuf[BUFLEN]; /* reception buffer */
uint32_t taddr_n; /* server IP addr. (net/host ord) */
uint16_t tport_n, tport_h; /* server port number (net/host ord) */
int s, len;
int result;
struct sockaddr_in saddr; /* server address structure */
struct in_addr sIPaddr; /* server IP addr. structure */
fd_set cset; // variables for timeout
struct timeval tval;
size_t n;
prog_name = argv[0];
if(argc < 4)
err_sys("Wrong number of parameters!\n");
// read address from first argument
taddr_n = inet_addr(argv[1]);
if (taddr_n == INADDR_NONE)
err_sys("Invalid address");
// read port number from second argument
if (sscanf(argv[2], "%" SCNu16, &tport_h)!=1)
err_sys("Invalid port number");
tport_n = htons(tport_h);
/* create the socket */
printf("Creating socket\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done. Socket fd number: %d\n",s);
/* prepare address structure */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = tport_n;
saddr.sin_addr = sIPaddr;
printf("trying to connect to the server...\n");
/* connect */
showAddr("Connecting to target address", &saddr);
Connect(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
// loop to request files
for (int i = 3 ; i < argc ; i++ ){ // i = 4 because the first file is the fourth argument
// check if file name is too big
if(strlen(argv[i]) >= BUFLEN - 6)
err_sys("The file name is too big for the buffer request!\n");
// create the string of bytes for the request
strcpy(request, "GET ");
strcat(request, argv[i]);
strcat(request, "\r\n");
len = strlen(request);
if(writen(s, request, len) != len){
printf("Write error\n");
break;
}
printf("waiting for response...\n");
// receive file from server
n = recv(s, rbuf, BUFLEN, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("Received reply from server\n");
uint32_t fsize;
printf("%s",rbuf);
if(strcmp(rbuf, "+OK\r\n") == 0){
n = recv(s, &fsize, 4, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
// received file dimension
fsize = ntohl(fsize);
}
while(fsize > 0){
printf("I am here1n\n");
// receive file
n = recv(s, rbuf, BUFLEN-1, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("I am here");
fsize -= n;
}
}
}
}
}
printf("===========================================================\n");
close(s);
exit(0);
}
The recv in the client where I am supposed to receive the file just blocks without receiving anything. I don't understand what I am missing...
The issue here is a common one: You're not being careful with message boundaries.
In your client, you do a recv and check whether the number of bytes is greater than 0. But then you don't do more length checking. You next do a strcmp on a particular string you're expecting to receive (+OK\r\n). But you might have received 3 bytes (+OK) or you might have received 10: (+OK\r\nXXXXX) or more [aside: also, recv doesn't guarantee your byte string is null-terminated]. There is nothing stopping the kernel on the far side from batching the preamble plus subsequent bytes into a single TCP packet. Likewise, there is nothing preventing the local side from aggregating multiple TCP packets into a single buffer.
You must provide message boundaries. If you're expecting your next message to be 5 bytes, then you should receive exactly 5 bytes (and retry if you get fewer -- being careful to check for EOF too in case the other side aborted early). Or, alternatively stick a buffering layer in front of your receive logic so that it will receive up to some large amount, return to you the number of bytes you want, and then save whatever is in excess for a subsequent "receive" call.
To restate this in a different way: Your server sends +OK\r\n, then it sends a four-byte length, then it starts sending the file. But that means your first recv on the client side could be receiving the preamble, plus the length, plus the first N bytes of the file all in one system call.
TCP does not respect, provide or enforce message boundaries.
I wrote this server program to accept request from one client at a time ,serve the request and then wait for further request ,the outer while loop is supposed to keep running but the program terminates after exactly one request
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/signal.h>
#define SUCCESS 0
#define ERROR 1
#define END_LINE 0x0
#define SERVER_PORT 1306
#define MAX_MSG 100
static int words = 0;
static int letters = 0;
static int delim = 0;
int
main (int argc, char *argv[])
{
int i, serv_sd, cli_sd, cliLen;
struct sockaddr_in cliAddr, servAddr;
char line[MAX_MSG], buffer[MAX_MSG];
serv_sd = socket (AF_INET, SOCK_STREAM, 0);
if (serv_sd < 0)
{
perror ("cannot open socket ");
return ERROR;
}
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
/* servAddr.sin_addr.s_addr = htonl(INADDR_ANY); */
servAddr.sin_port = htons (SERVER_PORT);
printf (" Socket Id is %d, Server port is %d\n", serv_sd, SERVER_PORT);
if (bind (serv_sd, (struct sockaddr *) &servAddr, sizeof (servAddr)) < 0)
{
perror ("cannot bind port ");
return ERROR;
}
listen (serv_sd, 5);
while (1)
{
printf ("%s :: waiting for data on port TCP %u\n", argv[0],
SERVER_PORT);
cliLen = sizeof (cliAddr);
cli_sd = accept (serv_sd, (struct sockaddr *) &cliAddr, &cliLen);
if (cli_sd < 0)
{
perror ("cannot accept connection ");
return ERROR;
}
memset (line, 0x0, MAX_MSG);
while (recv(cli_sd, line, MAX_MSG, 0) != -1)
{
printf ("\n %s:: Received from %s: TCP port %d << %s\n", argv[0],
inet_ntoa (cliAddr.sin_addr),
ntohs (cliAddr.sin_port), line);
words++;
int line_size = strlen (line);
for (i = 0; i < line_size; i++)
{
if (isalnum (line[i]) != 0)
letters++;
else
delim++;
}
printf("\nwords: %d, letters: %d\n,",words,letters);
send(cli_sd, &words, 4, 0);
send(cli_sd, &letters, 4, 0);
send(cli_sd, &delim, 4, 0);
memset (line, 0x0, MAX_MSG);
}//receiver
}//while
}
client
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<stdio.h>
#include<unistd.h>
#define MAX 100
int
main (int argc, int *argv[])
{
int sock_desc, rc, i, serv_port, letters, words, delim;
struct sockaddr_in localAddr, servAddr;
if (argc < 4)
{
printf
("usage: %s <server IP> <Server Port> <data1> <data2> ... <dataN>\n",
argv[0]);
exit (1);
}
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr (argv[1]);
serv_port = atoi (argv[2]);
servAddr.sin_port = htons (serv_port);
sock_desc = socket (AF_INET, SOCK_STREAM, 0);
if (sock_desc < 0)
{
perror ("cannot open socket ");
exit (1);
}
rc = connect (sock_desc, (struct sockaddr *) &servAddr, sizeof (servAddr));
if (rc < 0)
{
perror ("cannot connect ");
exit (1);
}
for (i = 3; i < argc; i++)
{
rc = send (sock_desc, argv[i], strlen (argv[i]) + 1, 0);
if (rc < 0)
{
perror ("Connection lost! ");
exit (1);
}
// printf ("\n %s::Data %d Sent--> %s", argv[0], i - 2, argv[i]);
recv(sock_desc, &words, 4, 0);
recv(sock_desc, &letters, 4, 0);
recv(sock_desc, &delim, 4, 0);
}
printf ("\n");
// close(sock_desc);
printf("\n\nThe message you sent had %d letters, %d words and %d delimiter.\n\n",letters,words,delim+words);
return 0;
}
Your server isn't properly checking if the client shutdown. recv will return 0 if the other side closed the connection. As a result, when you try to call send the server processes gets a SIGPIPE signal. Since you don't have a signal handler for that signal, the process exits.
You need to save the return value of recv and check if it's either -1 (for an error) or 0 (for a shutdown). The return value of send should be checked as well. Also, be sure to close the accepted socket when the inner loop exits.
#include <signal.h>
....
int rval;
...
signal(SIGPIPE,SIG_IGN); // ignore SIGPIPE
...
while ((rval=recv(cli_sd, line, MAX_MSG, 0)) != 0)
{
if (rval == -1) {
perror("recv failed");
break;
}
printf ("\n %s:: Received from %s: TCP port %d << %s\n", argv[0],
inet_ntoa (cliAddr.sin_addr),
ntohs (cliAddr.sin_port), line);
words++;
int line_size = strlen (line);
for (i = 0; i < line_size; i++)
{
if (isalnum (line[i]) != 0)
letters++;
else
delim++;
}
printf("\nwords: %d, letters: %d\n,",words,letters);
if (send(cli_sd, &words, 4, 0) == -1) {
perror("send 1 failed");
break;
}
if (send(cli_sd, &letters, 4, 0) == -1) {
perror("send 1 failed");
break;
}
if (send(cli_sd, &delim, 4, 0) == -1) {
perror("send 1 failed");
break;
}
memset (line, 0x0, MAX_MSG);
}//receiver
close(cli_sd);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
My problem statement was to create,update,delete,display record using client server program.
Here is mine code for client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
/* BufferLength is 100 bytes */
#define BufferLength 150
/* Default host name of server system. Change it to your default */
/* server hostname or IP. If the user do not supply the hostname */
/* as an argument, the_server_name_or_IP will be used as default*/
#define SERVER "The_server_name_or_IP"
/* Server's port number */
#define SERVPORT 3111
#define ID_ZERO "ID CAN'T BE ZERO"
#define FILE_ERR "CAN'T OPEN FILE"
#define ID_EXIST "ID ALREADY EXIST"
#define DEL_OK "Deleted Record"
#define CREATED_RECORD "CREATED_RECORD"
#define EMP_NOT_FOUND "EMP NOT FOUND"
#define UPDATED_RECORD "UPDATED RECORD"
#define BufferLength 150
/* Pass in 1 parameter which is either the */
/* address or host name of the server, or */
/* set the server name in the #define SERVER ... */
#pragma pack(1)
struct emprec
{
int empid;
int operation;
char name[200];
};
#pragma pack(0)
typedef struct emprec emp;
char data1[100];
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int count=0;
int totalcnt = 0;
emp temp1;
struct hostent *hostp;
unsigned char* datas = (unsigned char*)malloc(sizeof(temp1));
/* The socket() function returns a socket */
/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
printf("Client-socket() OK\n");
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the following %s, port %d ...\n", server, SERVPORT);
}
else
/*Use the default server name or IP*/
strcpy(server, SERVER);
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
{
/* When passing the host name of the server as a */
/* parameter to this program, use the gethostbyname() */
/* function to retrieve the address of the host server. */
/***************************************************/
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}
/* After the socket descriptor is received, the */
/* connect() function is used to establish a */
/* connection to the server. */
/***********************************************/
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
printf("Connection established...\n");
/* Send string to the server using */
/* the write() function. */
/*********************************************/
/* Write() some string to the server. */
while(1)
{
printf("Enter the choice\n");
printf("1- Insert a new record into file\n");
printf("2- Update the record\n");
printf("3- Display the records\n");
printf("4- Delete the record\n");
printf("5- Close the connection with the server\n");
int choice;
scanf("%d",&choice);
switch(choice){
case 1:
//emp temp1;
temp1.operation=1;
printf("Enter the id of the record\n");
scanf("%d",&temp1.empid);
if(temp1.empid==0)
{
printf("id cannot be zero\n");
break;
}
printf("Enter name correspond to that id\n");
scanf("%s",temp1.name);
if(strlen(temp1.name)==0)
{
printf("name cannot be empty\n");
break;
}
//printf("id that is being sent is %d\n",temp1.empid);
//printf("Name sent is %s\n",temp1.name);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
}
// }//else loop
totalcnt = 0;
// while(totalcnt < BufferLength)
// {
/* Wait for the server to echo the */
/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer, 100);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
// }
printf("Client-read() is OK\n");
printf("Echoed data from the following server: %s\n", buffer);
if(strcmp(buffer,CREATED_RECORD)==0){
count++;
printf("count incremented\n");
}
break;
//}//while loop
case 2: //Update the record
{
//emp temp21;
temp1.operation=2;
printf("Enter the id for which the record is to update \n");
scanf("%d",&temp1.empid);
printf("Enter name correspond to that id\n");
scanf("%s",temp1.name);
printf("id that is being sent t update is %d\n",temp1.empid);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
}
// }//else loop
totalcnt = 0;
//while(totalcnt < BufferLength)
//{
/* Wait for the server to echo the */
/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer, 25);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
//}
printf("Client-read() is OK\n");
printf("Echoed data from the following server: %s\n", buffer);
break;
case 3: //display
{
//emp temp31;
printf("IN DISPLAY\n");
printf("value of count is %d\n",count);
temp1.operation=3;
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
// printf("Waiting the %s to echo back...\n", server);
}
//emp temmp;
int ii =1;
while(ii<=count){
printf("value of count is %d\n",count);
rc= read(sd,&buffer,100);
memcpy(&temp1,buffer,sizeof(temp1));
printf("\nid is = %d name is = %s\n",temp1.empid,temp1.name);
ii++;
printf("value of ii is %d\n",ii);
}
printf("display loop ended\n");
//ii=0;
/*if(rc < 0)
{
perror("Server-read() error");
close(sd);
exit (-1);
}
else if(rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}*/
//}
break;
}
break;
case 4:
{
emp temp41;
temp1.operation=4;
printf("Enter id to be deleted \n");
scanf("%d",&temp1.empid);
printf("enter to be deleted is %d\n",temp1.empid);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
//sleep(10);
printf("sending\n");
rc =write(sd,datas,sizeof(temp1));
printf("sent\n");
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
count--;
}
rc= read(sd,&buffer,100);
//FILE_ERR
printf("Message from server is %s\n",buffer);
if(strcmp(buffer,FILE_ERR)==0){
printf("Server cant open the file.... please check at the server end\n");
close(sd);
exit(0);
//count++;
//printf("count incremented\n");
}
// if(
break;
}
case 5: // Shutdown case
{
//emp temp51;
temp1.operation=5;
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
//sleep(10);
printf("Closing client and asked server too to close\n");
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
//printf("Client-write() is OK\n");
//printf("String successfully sent!\n");
//printf("Waiting the %s to echo back...\n", server);
}
close(sd);
exit(0);
break;
}
}//switch bracket
}//switch
}//while 1
}//main
Here is mine code for server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
/* BufferLength is 100 bytes */
/* Server port number */
//ALL CONSTANTS
#define SERVPORT 3111
#define ID_ZERO "ID CAN'T BE ZERO"
#define FILE_ERR "CAN'T OPEN FILE"
#define ID_EXIST "ID ALREADY EXIST"
#define DEL_OK "Deleted Record"
#define CREATED_RECORD "CREATED_RECORD"
#define EMP_NOT_FOUND "EMP NOT FOUND"
#define UPDATED_RECORD "UPDATED RECORD"
#define BufferLength 150
#pragma pack(1)
struct emprec
{
int empid;
int operation;
char name[20];
};
#pragma pack(0)
typedef struct emprec emp;
int main()
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1,count=0;
int i=1;//use only one int
int flag1=0;//use only one flag
char temp;
char buffer[BufferLength];
char sbuf[25];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;
FILE *fd=NULL,*fd1=NULL;
fd_set read_fd;
emp temp2,temp8,temp3;
unsigned char* sdata = (unsigned char*)malloc(sizeof(temp2));
/* The socket() function returns a socket descriptor */
/* representing an endpoint. The statement also */
/* identifies that the INET (Internet Protocol) */
/* address family with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/************************************************/
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
/* Just exit */
exit (-1);
}
else
printf("Server-socket() is OK\n");
/* The setsockopt() function is used to allow */
/* the local address to be reused when the server */
/* is restarted before the required wait time */
/* expires. */
/***********************************************/
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
printf("Server-setsockopt() is OK\n");
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* connect to any client that used port 3005. */
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
/* Close the socket descriptor */
close(sd);
/* and just exit */
exit(-1);
}
else
printf("Server-bind() is OK\n");
/* The listen() function allows the server to accept */
/* incoming client connections. In this example, */
/* the backlog is set to 10. This means that the */
/* system can queue up to 10 connection requests before */
/* the system starts rejecting incoming requests.*/
/*************************************************/
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
printf("Server-Ready for client connection...\n");
/* The server will accept a connection request */
/* with this accept() function, provided the */
/* connection request does the following: */
/* - Is part of the same address family */
/* - Uses streams sockets (TCP) */
/* - Attempts to connect to the specified port */
/***********************************************/
/* accept() the incoming connection request. */
int sin_size = sizeof(struct sockaddr_in);
if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
printf("Server-accept() is OK\n");
/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
//printf("Got connection from the f***ing client: %s\n", inet_ntoa(their_addr.sin_addr));
while(1){
/* The select() function allows the process to */
/* wait for an event to occur and to wake up */
/* the process when the event occurs. In this */
/* example, the system notifies the process */
/* only when data is available to read. */
/***********************************************/
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
//FD_ZERO(&read_fd);
//FD_SET(sd2, &read_fd);
//rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
//if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
//{
/* Read data from the client. */
totalcnt = 0;
//while(totalcnt < BufferLength)
//{
/* When select() indicates that there is data */
/* available, use the read() function to read */
/* 100 bytes of the string that the */
/* client sent. */
/***********************************************/
/* read() from client */
rc= read(sd2,&buffer,100);
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}
memcpy(&temp2,buffer,sizeof(temp2));
printf("operation is %d\n",temp2.operation);
// declare it upwards
if (temp2.operation==1)//write record
{
printf("in write record\n");
printf("id is %d\n",temp2.empid);
printf("name is %s\n",temp2.name);
fd = fopen("/home/abc/Desktop/test34.txt","a+");
while(i<=count)
{
printf("value of i is %d and count is %d\n",i,count);
fread(&temp3.empid,sizeof(temp3.empid),1,fd);
fread(&temp3.name,sizeof(temp3.name),1,fd);
if(temp2.empid==temp8.empid)
{
printf("in create:: going in id checking loop\n");
flag1=1;
temp8.empid=0;
i=0;
break;
}
i++;
}
if (flag1==1)
{
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,ID_EXIST);
printf("temp2.empname is %s\n",temp2.name);
rc = write(sd2, sbuf, sizeof(sbuf));
i=0;
flag1=0;
//break;
}
else
{
count++;
fwrite(&temp2.empid,sizeof(temp2.empid),1,fd);
fwrite(&temp2.name,20,1,fd);
fclose(fd);
sleep(1);
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,CREATED_RECORD);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
if(rc <0)
{
perror("Server-write() error");
/* Get the error number. */
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
printf("Server-write() is OK\n");
}
}//else bracket
}
if (temp2.operation==2)//update
{
memcpy(&temp2,buffer,sizeof(temp2));
printf("in case update\n");
printf("id is %d\n",temp2.empid);
printf("name is %s\n",temp2.name);
int id,flag=0,i=1;
//emp temp4;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
id = temp2.empid;
printf("id to search is %d\n",id);
i=1;
while(i<=count)
{
fread(&temp8.empid,sizeof(temp8.empid),1,fd);
printf("Debbugging id read is %d\n",temp8.empid);
if(temp2.empid==temp8.empid)
{
int size = ftell(fd);
printf("pointer is at position %d\n",size);
printf("emp id found\n");
fseek(fd,size,SEEK_SET);
printf("data to write is %s\n",temp2.name);
fwrite(&temp2.name,20,1,fd);
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,UPDATED_RECORD);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
flag=1;
break;
}
i++;
}//while inside if
if(flag!=1)
{
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,EMP_NOT_FOUND);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
printf("No emp found");
flag=0;
}
fclose(fd);
}//if update
if (temp2.operation==3)//display
{
printf("In display\n");
emp temp6;
int i =1;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
while(i<=count)
{
fread(&temp6.empid,sizeof(temp6.empid),1,fd);
fread(&temp6.name,sizeof(temp6.name),1,fd);
printf("\nid is = %d name is = %s\n",temp6.empid,temp6.name);
memset(sdata,0,sizeof(temp6));
memcpy(sdata,&temp6,sizeof(temp6));
printf("temp2.empname is %s\n",temp2.name);
rc = write(sd2, sdata, sizeof(temp6));//add a check here
sleep(1);
i++;
}
fclose(fd);
}//if display
if (temp2.operation==4)//delete record - NOT YET COMPLETE
{
printf("In case 4 THAT IS DELETE \n");
int found =0,i=1;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,FILE_ERR);
printf("sbuf is %s\n",sbuf);
rc = write(sd2, sbuf, sizeof(sbuf));
return 1;
}
fd1 = fopen("/home/abc/Desktop/test335.txt","a+");
if(fd1==NULL)
{
printf("File cannot be opened\n");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,FILE_ERR);
printf("sbuf is %s\n",sbuf);
rc = write(sd2, sbuf, sizeof(sbuf));
return 1;
}
printf("name to search is %s\n",temp2.name);
printf("id to delete is %d\n",temp2.empid);
emp temp7,temp10;
memcpy(&temp10,buffer,sizeof(temp10));
printf("temp 10 id to delete is %d\n",temp10.empid);
while(i<=count){
fread(&temp7.empid,sizeof(temp7.empid),1,fd);
fread(&temp7.name,sizeof(temp7.name),1,fd);
if(temp2.empid==temp7.empid){
printf("A requested by name found and deleted\n");
found = 1;
count--;
}else{
fwrite(&temp7,sizeof(temp7),2,fd1);
}
if(!found)
{
printf("cannot found the record\n");
}
i++;
}
fclose(fd);
fclose(fd1);
remove("/home/abc/Desktop/test34.txt");
rename("/home/abc/Desktop/test335.txt","/home/tarun/Desktop/test34.txt");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,DEL_OK);
rc = write(sd2, sbuf, sizeof(sbuf));
//for debugging
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
i=0;
while(i<=count)
{
fread(&temp7.empid,sizeof(temp7.empid),1,fd);
fread(&temp7.name,sizeof(temp7.name),1,fd);
printf("\nid is = %d name is = %s\n",temp7.empid,temp7.name);
i++;
}
}// if delete record
/* When the data has been sent, close() */
/* the socket descriptor that was returned */
/* from the accept() verb and close() the */
/* original socket descriptor. */
/*****************************************/
/* Close the connection to the client and */
/* close the server listening socket. */
/******************************************/
if (temp2.operation==5)//close connection
{
printf("client has asked to shutdown ... Its time to go bbye\n");
close(sd2);
close(sd);
exit(0);
return 0;
}
}
}
I have tryed to test all the cases possible.But i request if you have please review the code and comment where more checks can be added.
Also i am getting a problem in delete record after deleteing i am not able to get the exact values please tell me whats the issue
there are several logic errors in the posted code.
Here is the details of one such error:
rc= read(sd,&buffer,100);
memcpy(&temp1,buffer,sizeof(temp1));
printf("\nid is = %d name is = %s\n",temp1.empid,temp1.name);
1) read() does not append a string terminator byte
2) memcpy() is copying the full buffer[] rather than just the number of bytes read
3) printf...%s... does not stop printing until it encounters a '\0' byte.
What happens if the number of bytes read is only a few bytes
(this can happen, and often does, which is the reason to use a 'select()/read()' with the socket set to non-blocking, loop to assure getting all the required/desired bytes of input.)
only copy the actual number of read bytes 'rc' to the 'temp1' struct.
Then insert a '\0' as the next byte.
Note: the socket has not been set to 'non-blocking' so the code will 'hang' until 100 bytes are read or the socket times out.
I have a tcp echo server that creates a pthread for each client that connects to it. For each connection, I have a variable nbOfClients that increments.
When a client closes its connection, I detect it and decrease the number of clients. However the server keeps thinking that the client it alive and keeps on trying to read/write from the socket. I guessed that it was because of the thread that created the client and I tries to kill the thread with pthread_cancel all to non avail.
I want to kill the pthread associated to a certain client that closes its connection.
How can I go about it?
Here's my code :
static int nbOfClients = 0;
static pthread_t tid;
int main (int argc, char *argv[]) {
int bytes_to_read, arg, listen_sd, new_conn, sockfd, client_len, port;
struct sockaddr_in server, client_addr;
char *bp, buf[BUFLEN];
ssize_t n;
sockfd = 0;
switch(argc) {
case 1:
port = SERVER_TCP_PORT; // Use the default port
break;
case 2:
port = atoi(argv[1]); // Get user specified port
break;
default:
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(1);
}
// Create a stream socket
if ((listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
error("Cannot Create Socket!");
// set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
arg = 1;
if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1)
error("setsockopt");
// Bind an address to the socket
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY); // Accept connections from any client
if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1)
error("bind error");
listen(listen_sd, MAX_CONNECTIONS); ///put a define constant indicating the maximum number of clients #define NB_CLIENTS 3
while (TRUE) {
client_len = sizeof(client_addr);
if ((new_conn = accept(listen_sd, (struct sockaddr *) &client_addr, (socklen_t *)&client_len)) == -1)
error("accept error");
if(new_conn > 0) {
if(nbOfClients < MAX_CONNECTIONS) {
printf("just here\n");
printf(">> Initializing remote address: %s\n", inet_ntoa(client_addr.sin_addr));
nbOfClients++;
fclose(fp);
printf("Connections to date: %u \n",nbOfClients);
printf("make thread\n");
pthread_create(&tid,NULL,&echo, (void *)new_conn);
printf("had thread\n");
}
else {
printf("connection limit reached\n");
if(send(new_conn, "Server full!\n", 13, 0) == -1)
perror("send");
close(new_conn);
}
}
}
return(0);
}
void * echo(void *arg) {
char buf[BUFSIZE]; /* message buffer */
int n, i = 0;
bzero(buf, BUFSIZE);
if(send((int)arg, "Welcome!!\n", 20, 0) == -1)
perror("send");
detect_closed_connection(arg);
while(TRUE) {
n = read((int)arg, buf, BUFSIZE);
/**read: read input string from the client*/
if(n < 0) {
perror("error reading from socket");
}
printf("Server received from client, %d bytes: %s\n", n, buf);
/**write: echo the input string in UPPERCASE back to the client*/
int len = strlen(buf);
for(i = 0; buf[i]; i++)
buf[i] = toupper(buf[i]);
n = write((int)arg, buf, len);
if(n < 0) {
error("ERROR writing to socket");
}
}
}
void detect_closed_connection(void * listenSocket) {
struct pollfd pfd;
pfd.fd = (int)listenSocket;
pfd.events = POLLIN | POLLHUP | POLLRDNORM;
pfd.revents = 0;
while(pfd.revents == 0) {
if(poll(&pfd, 1, 100) > 0) {
// if result > 0, this means that there is either data available on the
// socket, or the socket has been closed
char buffer[32];
if (recv((int)listenSocket, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
// if recv returns zero, that means the connection has been closed:
nbOfClients--;
pthread_cancel(tid);
}
}
}
}
Thanks.
You should check read() for returning 0 in the thread servering the client, as read() returns 0 in case the peer (client here) closed the connection.
After this line
n = read((int)arg, buf, BUFSIZE);
add
if (0 == n)
{
fprintf(stderr, "The client closed the connection.\n");
break;
}
Just before the thread function leave you could add the statement to decrement the number of running threads.
Also be aware that nbOfClients is accessed concurently by all the "client"-threads as well as by the main thread, so accessing it shall be protected, for example by using a mutex.
There is another issues, as the call to strlen() on the buffer read expects the buffer to be 0-terminate, which does not necessarily needs ot be the case, even if you sent 0-terminated "strings". read() might very well return the "string" the client sent in more then one part. So loop around read() until the 0-terminator had been received.
Do not make the thread end itself by calling pthread_cancel(), use pthread_exit() instead.
I built very basic UDP chat using C language and Fedora 16 OS.
When my server connect, he got 5 ports and listen to them.
My problem is: when I'm trying to connect to the server with new client but gives him port that my server don't know, I want him to exit Immediately.
I don't know how to check the "MSG_DONTWAIT" flag.
Here is my code:
Server side:
#define MAX_MESSAGE_SIZE 1024
#define SERVER_CONNECTIONS 5
// Implementation of server that manages a chat.
#include "server.h"
int main(int argc,char* argv[])
{
if(argc != 2) //check if user insert more then one argument to the program
{
printf("Usage server <port>\n");
fflush(stdout);
exit (-1);
}
/*!
========Server creation flow:========
1) create the socket
2) bind the socket to a port
3) recvfrom (read from socket)
4) sendto (close the socket)
5) close the socket
*/
//!------------------------------------- 1) create the socket-------------------------------------
//!------------------------------- 2) bind the socket to a port-----------------------------------
int fd[SERVER_CONNECTIONS]; //socket descriptor
int port[SERVER_CONNECTIONS]; //socket fd port
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
port[i] = atoi(argv[1])+i;
}
create_sockets(fd, port);
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int maxfd = find_maxfd(fd);
struct sockaddr_in cli; //used by read() & write()
int cli_len = sizeof(cli); //used by read() & write()
fd_set readfds;
fd_set writefds;
struct timeval timeout;
timeout.tv_sec = 1;
int nbytes=0;
while(1)
{
FD_ZERO(&readfds);
FD_ZERO(&writefds);
for(i=0; i<SERVER_CONNECTIONS; i++)
{
FD_SET(fd[i], &readfds);
FD_SET(fd[i], &writefds);
}
/* Now use FD_SET to initialize other fd’s that have already been returned by accept() */
if (select(maxfd+1, &readfds, 0, 0, 0) < 0)
{
perror("select");
exit(1);
}
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------- recvfrom (read from socket)-----------------------------------
if(FD_ISSET(fd[i], &readfds))
{
fprintf(stderr, "ready to read from %d\n", fd[i]);
memset(&buf, 0, sizeof(buf)); //init buf
if((nbytes = recvfrom(fd[i], buf, sizeof(buf), 0 /* flags */, (struct sockaddr*) &cli, (socklen_t*)&cli_len)) < 0)
{
perror("recvfrom");
exit(1);
}
//!------------------------------- sendto (close the socket)-----------------------------------
FD_ZERO(&writefds);
FD_SET(fd[i], &writefds);
if (select(maxfd+1, 0, &writefds, 0, &timeout) < 0)
{
perror("select");
exit(1);
}
if(FD_ISSET(fd[i], &writefds))
{
fprintf(stderr, "ready to write to %d\n", fd[i]);
string_to_hex(buf);
if ((nbytes = sendto(fd[i], buf, strlen(buf), 0 /* flags */, (struct sockaddr*) &cli, sizeof(cli))) < 0)
{
perror("sendto");
exit(1);
}
}
}
}
}
return 0;
}
void create_sockets(int fd[], int port[])
{
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------------- 1) create the socket-------------------------------------
if((fd[i] = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
//!------------------------------- 2) bind the socket to a port-----------------------------------
struct sockaddr_in srv; //used by bind()
srv.sin_family = AF_INET; //use the Internet address family
srv.sin_port = htons(port[i]); //socket ‘fd’ to port
srv.sin_addr.s_addr = htonl(INADDR_ANY); //a client may connect to any of my addresses
if(bind(fd[i], (struct sockaddr*) &srv, sizeof(srv)) < 0)
{
perror("bind");
exit(1);
}
}
}
int find_maxfd(int fd[])
{
int i=0;
int res=fd[0];
for(i=1; i<SERVER_CONNECTIONS; i++)
{
if(fd[i]>res)
{
res = fd[i];
}
}
return res;
}
void string_to_hex(char buf[])
{
int buf_size = strlen(buf);
char result[buf_size*3+1];
memset(&result, 0, sizeof(result));
char temp[4];
int i=0;
for (i=0; i<buf_size-1; i++)
{
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X:", (int)buf[i]);
strcat(result, temp);
}
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X", (int)buf[i]);
strcat(result, temp);
strcpy(buf, result);
}
Client side:
#define MAX_MESSAGE_SIZE 1024
// Implementation of client that will use the chat.
#include "client.h"
int main(int argc,char* argv[])
{
if(argc != 3) //check if user insert more then one argument to the program
{
printf("Usage client <host name> <port>\n");
fflush(stdout);
exit(-1);
}
/*!
========Client creation flow:========
1) create the socket
2) sendto (close the socket)
3) recvfrom (read from socket)
4) close the socket
*/
fprintf(stderr, "please enter something: \n");
//!------------------------------------- 1) create the socket-------------------------------------
int fd; //socket descriptor
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in srv; //used by sendto()
srv.sin_family = AF_INET;
srand ( time(NULL) ); //new random seed
int rand_num = (rand() % 5) + atoi(argv[2]); //
srv.sin_port = htons(rand_num);
char *srv_name = argv[1];
struct hostent *hp; //ptr to host info for remote
hp = gethostbyname(srv_name);
if( hp == NULL)
{
herror("gethostbyname");
exit(-1);
}
srv.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; //set IP Address to "srv_name"
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int nbytes=0;
while(1)
{
//!------------------------------------- 2) sendto (close the socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init buf
fgets(buf, sizeof(buf), stdin); //get input from user
if(strcmp(buf, "quit\n") == 0)
{
break;
}
if(!((strlen(buf) == 1) && (buf[1] == '\n')))
{
buf[strlen(buf)-1] = '\0';
}
//write_to_server(fd, buf, srv);
if ((nbytes = sendto(fd, buf, strlen(buf), MSG_DONTWAIT /* flags */, (struct sockaddr*) &srv, sizeof(srv)) < 0))
{
perror("sendto");
exit(1);
}
//!------------------------------------- 3) recvfrom (read from socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init read_buf
//read_from_server(fd, buf);
if((nbytes = recvfrom(fd, buf, sizeof(buf), 0 /* flags */, 0, 0) < 0))
{
perror("recvfrom");
exit(1);
}
if( (errno == EAGAIN) || (errno == EWOULDBLOCK ) )
{
perror("EWOULDBLOCK");
exit(1);
}
printf("%s\n", buf); //print result to client
fflush(stdout);
}
//!------------------------------------- close the socket-------------------------------------
close(fd);
return 0;
}
I got it..
You need to use connect function from client and the "MSG_DONTWAIT" flag.
then when the client connect and you type anything he exit right away..
//!--------------- 2) connect to the server--------------------------
if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) //connect to server "srv_name"
{
perror("connect");
exit(-1);
}