Server terminates exactly after one request is handled - c

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);

Related

Stuck with i/o multiplexing

/* Server.c */
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include <string.h>
#define SERV_TCP_PORT 25000
#define BUFSIZE 1024
void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax);
void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax){
char user[BUFSIZE] = "user", pass[BUFSIZE] = "12345";
char username[BUFSIZE], password[BUFSIZE];
recv(i, username, BUFSIZE, 0);
for (j = 0; j <= fdmax; j++) {
if (FD_ISSET(j, &master)) {
if (j != sockfd && j== i) { // to itself but not all
if (j!=sockfd) {
printf("Username receive [%s] from socket [ %d ]\n", username, i);
if(strcmp(username, user)==0)
{
send(j, username, BUFSIZE, 0);
printf("\nSend the username [ %s ] via socket [%d]\n", username, j);
//bzero(buffer, BUFSIZE);
recv(i, password, BUFSIZE, 0);
for (j = 0; j <= fdmax; j++) {
if (FD_ISSET(j, &master)) {
if (j != sockfd && j== i) { // to itself but not all
if (j!=sockfd) {
printf("Password [%s] from socket [ %d ]\n", password, i);
if(strcmp(password, pass)==0)
{
send(j, password, BUFSIZE, 0);
printf("\nSend the password [ %s ] via socket [%d]\n", password, j);
}
}
}
}
}
}
}
}
}
}
}
int main(int argc, char** argv){
fd_set master;
fd_set read_fds;
struct sockaddr_in myaddr;
struct sockaddr_in remoteaddr;
int fdmax;
int sockfd;
int new_sockfd;
char buffer[BUFSIZE];
int nbytes;
int yes = 1;
int addrlen;
int i, j;
pid_t pid;
sigset_t set1;
sigemptyset(&set1);
sigaddset(&set1, SIGTSTP); //ctrl+z
sigprocmask(SIG_BLOCK, &set1, NULL);
FD_ZERO(&master);
FD_ZERO(&read_fds);
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0) ) == -1){
printf("\nsocket() error!!!\n");
exit(1);}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
printf("\nSetsockopt() error!!!\n");
exit(1);}
bzero( (char *)&myaddr, sizeof(myaddr) );
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(SERV_TCP_PORT);
bzero(&(myaddr.sin_zero), 8);
if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1){
printf("\nbind() error!!!\n");
exit(1);}
if (listen(sockfd, 10) == -1){
printf("\nlisten() error!!!\n");
exit(1);}
FD_SET(sockfd, &master);
fdmax = sockfd; // only sockfd at this moment
for(;;){
read_fds = master;
if (pselect(fdmax+1, &read_fds, NULL, NULL, NULL, &set1) == -1){
printf("\nselect() error!!!\n");
exit(1); }
for(i=0; i<=fdmax; i++) {
if( FD_ISSET(i, &read_fds) ){
if (i == sockfd) {
addrlen = sizeof(remoteaddr);
if( (new_sockfd = accept(sockfd, &remoteaddr, &addrlen) ) == -1 ) {
printf("\naccept() error!!!\n");}
else {
FD_SET(new_sockfd, &master);
if(new_sockfd > fdmax){
fdmax = new_sockfd;}
printf("selectserver: new connection from %s on socket %d \n", inet_ntoa(remoteaddr.sin_addr), new_sockfd);
} // esle for accept()
} // else for i==sockfd
else
{ // if i != sockfd
if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {
if (nbytes == 0) {
printf("selectserver: socket %d hung up\n", i); }
else{
printf("\nrecv() error!!!\n"); } // else for nbytes == 0
close(i);
FD_CLR(i, &master); } // for recv
else{
for (j = 0; j <= fdmax; j++)
{
if (FD_ISSET(j, &master)) {
if (j != sockfd && j == i) { // to itself but not all
if (j!=sockfd)
{
printf("Message [ %s ] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
if(strcmp(buffer, "start")==0){
//printf("Message [%s] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
send(j, buffer, BUFSIZE, 0);
login(buffer, i, j, sockfd, master, fdmax);
}
else if(strcmp(buffer, "exit")==0){
printf("\nrecv() error!!!\n");
close(i);
FD_CLR(i, &master);
//break;
}
}
}
}
}
}
}
}
}
}
return 0;
}
This is server.c
/* Client.c */
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#define SERV_TCP_PORT 25000
#define BUFSIZE 1024
int main(int argc, char *argv[])
{
int sockfd;
char buffer[BUFSIZE+1];
struct sockaddr_in serv_addr;
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_TCP_PORT);
inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("\nsocket() error!!!\n");
}
if( (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr) )) < 0){
perror("\nconnect() error!!!\n");
}
printf("\nconnection with server: %s...\n", inet_ntoa(serv_addr.sin_addr));
do
{
bzero(buffer, BUFSIZE);
printf("\nEnter a message : [type /q to quit]");
scanf("%s", buffer);
printf("\nMessage [ %s ] send to server \n", buffer);
send(sockfd, buffer, BUFSIZE, 0);
bzero(buffer, sizeof(buffer));
recv(sockfd, buffer, BUFSIZE, 0);
printf("\nMessage [ %s ] received from server \n", buffer);
} while (strcmp(buffer, "/q"));
close(sockfd);
}
This is client.c
I want to solve the problem with Server.c, but it can't handle multiple clients simultaneously. When I am trying to take input from second client, it hang. The second client begins working after first client done his job.
I see several errors in the code.
When I compile server.c, I get this warning from clang:
server.c:128:32: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {
I think you intended this instead:
if ((nbytes = recv(i, buffer, sizeof(buffer), 0)) <=0)
Also on line 137 you have this:
if (FD_ISSET(j, &master)) {
... but master doesn't contain the results of your latest pselect() operation, so you probably wanted to do this instead:
if (FD_ISSET(j, &read_fds)) {
Once I corrected those two problems, I could connect to your server with telnet localhost 25000 and get reasonable behavior from it.
However, connecting with your client program resulted in only the first entered line of text being received. That is because your client blocks inside recv(sockfd, buffer, BUFSIZE, 0), and therefore will not process any further lines of text entered into stdin until after it has received some data from the server. If that's intentional behavior, then it's okay, but if you were intending for the clients to be able to send data to the server whenever the user enters text into stdin, you should probably update your client program to use select() in a way similar to how your server does. (On POSIX OS's [not Windows], you can have select() monitor STDIN_FILENO and treat stdin as if it was any other file-descriptor)

Calculate average of numbers in TCP connection

I have to calculate the average of numbers received by a server, then send it to client in a TCP connection in C. The program must be like this:
Client sends a message to server with numbers(for example): 2 10 12 --> 2 is number of data and 10 and 12 are the data. Server receives the numbers and sends the count of them to client(in this example count is "2"). It continues until client sends number "0". At this point, server has to send a message to client with number of data calculated and, in the same line, the average of them. If i send "2 10 12" and "2 5 6", server sends to client the message: "4 8.25". "4" is the number of data to calculate and "8.25" is average.
Until now i made the first part for client:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus= 0;
char buffsend[256];
char buffrecv[256];
char buff[256];
int i, n, length, ndata;
float average=0;
struct sockaddr_in simpleServer;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
/* create a streaming socket */
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for connecting */
simplePort = atoi(argv[2]);
/* setup the address structure */
/* use the IP address sent as an argument for the server address */
//bzero(&simpleServer, sizeof(simpleServer));
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
//inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port = htons(simplePort);
/* connect to the address and port with our socket */
returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Connect successful!\n");
}
else {
fprintf(stderr, "Could not connect to address!\n");
close(simpleSocket);
exit(1);
}
/* get the message from the server */
do {
bzero(buffsend, 256);
printf("insert num dati or terminate(write '0'): ");
fgets(buffsend,256,stdin);
n=atoi(buffsend);
if(n>6) {
printf("Error\n");
}
else {
length=strlen(buffsend);
for(i=0;i<n;i++) {
printf("insert number: ");
length=strlen(buffsend);
buffsend[length-1]=' ';
fgets(buffsend+length,256-length,stdin);
write(simpleSocket, buffsend, strlen(buffsend));
read(simpleSocket, buffrecv, 256);
}
ndata=atoi(buffrecv);
printf("DT %d\n", ndata);
}
} while((n!=0) && (n>0));
close(simpleSocket);
return 0;
}
And this for server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
char buff[256];
char message[256];
int n, i, DT;
int count=0;
float average=0;
struct sockaddr_in simpleServer;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for listening */
simplePort = atoi(argv[1]);
/* setup the address structure */
/* use INADDR_ANY to bind to all local addresses */
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
simpleServer.sin_port = htons(simplePort);
/* bind to the address and port with our socket */
returnStatus = bind(simpleSocket,(struct sockaddr *)&simpleServer,sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Bind completed!\n");
}
else {
fprintf(stderr, "Could not bind to address!\n");
close(simpleSocket);
exit(1);
}
/* lets listen on the socket for connections */
returnStatus = listen(simpleSocket, 5);
if (returnStatus == -1) {
fprintf(stderr, "Cannot listen on socket!\n");
close(simpleSocket);
exit(1);
}
while (1)
{
struct sockaddr_in clientName = { 0 };
int simpleChildSocket = 0;
int clientNameLength = sizeof(clientName);
/* wait here */
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
if (simpleChildSocket == -1) {
fprintf(stderr, "Cannot accept connections!\n");
close(simpleSocket);
exit(1);
}
/* handle the new connection request */
/* write out our message to the client */
do {
read(simpleChildSocket, buff, 256);
num=atoi(buff);
conta++;
DT=(conta)-1;
DT=write(simpleChildSocket, buff, strlen(buff));
printf("Message received: %s\n", buff);
bzero(buff, 256);
} while(num!=0);
close(simpleChildSocket);
}
close(simpleSocket);
return 0;
}
There are some fixes in your code, especially on the client side. It is more convenient to send a package with |size| |data| at once, than each number.
The server side receives the packet, reads the size and accumulates, reads the data and accumulates and then sends size to the client.
If the client sends 0, the server calculates the average and sends the result.
I believe it will serve as the initial idea.
cliente side, main loop:
/*--------cliente side---------*/
int iResult;/*iResult >1 get from connect*/
char buffsend[256];
char szTmp[50];
do {
menset(buffsend,0,256);/*zero memory*/
menset(szTmp,0,50);/*zero memory*/
printf("insert num dati or terminate(write '0'): ");
fgets(szTmp,50,stdin);
int n = atoi(szTmp);
if(n>6)
printf("Error\n");
else
{
sprintf(buffsend,"%d ",n);
for(int h=0;h<n;h++)
{
printf("insert number: ");
fgets(szTmp,50,stdin);
szTmp[strcspn(szTmp, "\n")] = 0;/*<---remove end line */
strcat(buffsend,szTmp);/*concatenate new num*/
strcat(buffsend," ");/*add space*/
}
}
/*send the data <len><space><data> exemp: 2 12 34*/
iResult = write( ConnectSocket, buffsend, strlen(buffsend) );
if (iResult == -1)
{
printf("send failed with error: -1\n");
close(ConnectSocket);
return 1;
}
menset(buffsend,0,256);/*zero memory*/
iResult = read(ConnectSocket, buffsend, 256);
if ( iResult > 0 )
printf("Bytes received: %d > %s \n", iResult,recvbuf);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
server side loop:
/*-------------server side------------*/
int iResult;/*At this point iResult is greater than 0, by the return of connect*/
int nNumerator;
int den;/*Accumulate sizes*/
float faverage;
nNumerator=0;
den = 0;
faverage=0;
do
{
memset(recvbuf,0,256);
iResult = read(ClientSocket, recvbuf, recvbuflen);
if (iResult > 0)
{
char bufftmp[25];
int numpart;
int iTmp;
numpart =0;
iTmp =0;
memset(bufftmp,0,25);
printf("Bytes received: %d\n", iResult);
printf("%s\n",recvbuf);
/*Traverses all received datar ecvbuf and separates the accumulating size into den,
and then accumulates the data in nNumerator*/
for(int k=0;k<iResult;k++)
{
bufftmp[iTmp++]=recvbuf[k];
if(recvbuf[k]==' ')
{
if(!numpart)/*is numpart zero*/
{
bufftmp[iTmp]='\0';//make space null
numpart=atoi(bufftmp);
den+=numpart;/*acumalate to average*/
printf("lenght: %d\n",numpart);/*get only length*/
memset(bufftmp,0,25);
if(numpart==0)
{
/*go to average*/
faverage = (float)nNumerator/(float)den;
}
}
else/* if numparte > 0 get data*/
{
bufftmp[iTmp]='\0';
printf("%s ",bufftmp);
nNumerator+=atoi(bufftmp);/*save in to buffer of int´s*/
memset(bufftmp,0,25);
}
iTmp=0;
printf("\n");
}
}
memset(recvbuf,0,256);
if(numpart)/*if not zero, send length of data to client*/
sprintf(recvbuf,"%d",numpart);
else/*if not, send average*/
sprintf(recvbuf,"%d %f",den,faverage);
iResult = write( ClientSocket, recvbuf, strlen(recvbuf));
if (iResult == -1)
{
printf("send failed with error: -1\n");
close(ClientSocket);
return 1;
}
}
else if (iResult == 0)
printf("Connection closing...\n");
else
{
printf("recv failed with error: -1\n");
close(ClientSocket);
return 1;
}
}while (iResult > 0);

Sending multiple messages over a TCP port

I have a program that creates a socket (server and client program) and sends a message via a TCP port using that socket. My question is, how can I exchange multiple messages?
Every time I send a message the port gets closed and I need to use another port to send another message.
For example, I have to send 2 numbers from the client to the server and the server needs to reply back the total sum of the numbers I send. How would I achieve sending undefined number or even 2 numbers over the SAME port?
Here are the codes (pretty much standard stuff):
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
char* Itoa(int value, char* str, int radix)
{
static char dig[] =
"0123456789"
"abcdefghijklmnopqrstuvwxyz";
int n = 0, neg = 0;
unsigned int v;
char* p, *q;
char c;
if (radix == 10 && value < 0) {
value = -value;
neg = 1;
}
v = value;
do {
str[n++] = dig[v%radix];
v /= radix;
} while (v);
if (neg)
str[n++] = '-';
str[n] = '\0';
for (p = str, q = p + (n-1); p < q; ++p, --q)
c = *p, *p = *q, *q = c;
return str;
}
void error (const char *msg)
{
perror (msg);
exit (1);
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
fprintf (stderr, "ERROR, no port provided\n");
exit (1);
}
//nova varijabla za sumiranje primljenih brojeva
int suma=0;
int sockfd, newsockfd, portno,i;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
for (i=0;i<2;i++)
{
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error ("ERROR opening socket");
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
portno = atoi (argv[1]);
portno+=i;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons (portno);
if (bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) error ("ERROR on binding");
//test za ispis otvorenog porta
printf("Uspjesno otvoren localhost na portu %d\n", portno);
listen (sockfd, 5);
clilen = sizeof (cli_addr);
newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error ("ERROR on accept");
memset (buffer, 0, 256);
n = read (newsockfd, buffer, 255);
if (n < 0) error ("ERROR reading from socket");
printf ("%d. proslan broj: %s\n", i+1, buffer);
//print
suma=suma+atoi(buffer);
//radi!! printf("suma je %d\n", suma);
//od klijenta: n = write (sockfd, buffer, strlen (buffer));
//char * itoa ( int value, char * str, int base );
Itoa(suma, buffer, 10);
n = write (newsockfd, buffer, strlen(buffer));
if (n < 0) error ("ERROR writing to socket");
close (newsockfd);
close (sockfd);
}
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error (const char *msg)
{
perror (msg);
exit (1);
}
int
main (int argc, char *argv[])
{
if (argc < 3)
{
fprintf (stderr, "usage %s hostname port\n", argv[0]);
exit (1);
}
int sockfd, portno, n,i;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
for (i=0;i<2;i++)
{
portno = atoi (argv[2]);
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error ("Ne mogu otvoriti socket!");
server = gethostbyname (argv[1]);
if (server == NULL)
{
fprintf (stderr, "Greska, ne postoji!\n");
exit (1);
}
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy ((char *) server->h_addr,
(char *) &serv_addr.sin_addr.s_addr,
server->h_length);
portno+=i;
serv_addr.sin_port = htons (portno);
if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error ("ERROR connecting");
printf ("%d. broj za slanje: ", i+1);
memset (buffer, 0, 256);
fgets (buffer, 255, stdin);
n = write (sockfd, buffer, strlen (buffer));
if (n < 0)
error ("ERROR writing to socket");
memset (buffer, 0, 256);
n = read (sockfd, buffer, 255);
if (n < 0)
error ("ERROR reading from socket");
if (i==1) printf ("Suma iznosi: %s\n", buffer);
close (sockfd);
}
return 0;
}
So, for example, I run the code and get this for the server side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./server2 5000
Uspjesno otvoren localhost na portu 5000
1. proslan broj: 45
Uspjesno otvoren localhost na portu 5001
2. proslan broj: 56
j#PC ~/Desktop/Mreze/Lab1/rijeseno $
And on the client side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./client2 localhost 5000
1. broj za slanje: 45
2. broj za slanje: 56
Suma iznosi: 101
I've tried putting a while loop so it loops the part with sending but without success. Please explain to me where should I even put it so it works. Thank you!
Here is a problem:
n = read (newsockfd, buffer, 255);
What you do, is you perform read once, and the data might not be fully available. The fact is, you need to read data, as long as you received the data completely, or detected EOF condition (-1 return value).
Generally you need to write more reliable code for receiving part, as it is not guaranteed on stream protocol that your message boundaries are kept in any form.
Here is a (very unoptimal, yet simple) code for reading data:
int readLine(int fd, char data[])
{
size_t len = 0;
while (len < maxlen)
{
char c;
int ret = read(fd, &c, 1);
if (ret < 0)
{
data[len] = 0;
return len; // EOF reached
}
if (c == '\n')
{
data[len] = 0;
return len; // EOF reached
}
data[len++] = c;
}
}
And usage example:
char buffer[256];
int num1, num2;
readLine(newsockfd, buffer);
num1 = atoi(buffer);
readLine(newsockfd, buffer);
num2 = atoi(buffer);
First Put your connection() function before and close() after for loop. Just for an idea
connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)
for (i=0;i<n;i++){
// do you introspection with server
// actually send number to server
}
// Code to read result: SUM from server
close (sockfd);

Can't close non-blocking UDP socket in C Fedora16

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);
}

TCP FIN not sent on doing 'close ()' for a multi-threaded TCP client

I have written below multi-threaded TCP client which basically spawns a separate thread for receiving the data however the data is being written in the main thread only having taken input from the user on standard input.
Now, having pressed ctrl^D then implementation comes out of the loop (around the getline () call) and closes the socket descriptor but no FIN is seen on the wire. However, replacing close() with shutdown () makes a difference. With close() no FIN is sent on the wire but with shutdown(fd, SHUT_WR) FIN is sent on the wire?
Why is this difference?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
void *receiver (void *arg);
pthread_t thrid;
int sockfd;
int reUse = 0;
int
main (int argc, char *argv[])
{
struct sockaddr_in servaddr;
struct sockaddr_in clntaddr;
char *line;
size_t len = 0;
size_t read;
int bytes;
if (argc < 6)
{
printf
("Usage:%s <Server Ipv4 address> <Server Port> <SO_REUSEADDR Yes(1)/No(0))> <Close(0)/SHUT_RD(1)/SHUT_WR(2)/SHUT_RDWR(3)> <sleep (in sec)> [Client IPv4 address] [Client Port]\n",
argv[0]);
return -1;
}
/*
* AF_INET, AF_INET6, AF_UNIX, AF_NETLINK
* SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_RAW
*/
if ((sockfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
printf ("Failed to create socket: %s\n", strerror (errno));
return -1;
}
/*
* set SO_REUSEADDR option for the UDP server socket
*/
reUse = atoi (argv[3]);
if (reUse)
{
int i = 1;
setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &i,
sizeof (i));
}
bzero (&clntaddr, sizeof (struct sockaddr_in));
if (argc == 8)
{
printf ("doing bind......\n");
clntaddr.sin_family = AF_INET;
clntaddr.sin_port = htons (atoi (argv[7]));
inet_aton (argv[6], &clntaddr.sin_addr);
if (bind
(sockfd, (struct sockaddr *) &clntaddr,
sizeof (struct sockaddr_in)) == -1)
{
perror ("Failed to bind");
close (sockfd);
return -1;
}
}
bzero (&servaddr, sizeof (struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (atoi (argv[2]));
inet_aton (argv[1], &servaddr.sin_addr);
if (-1 ==
connect (sockfd, (struct sockaddr *) &servaddr,
sizeof (struct sockaddr_in)))
{
printf ("Failed to connect: %s\n", strerror (errno));
return -1;
}
if (pthread_create (&thrid, NULL, receiver, NULL) < 0)
{
printf ("Failed to create thread\n");
}
while ((read = getline (&line, &len, stdin)) != -1)
{
bytes = send (sockfd, line, len, 0);
if (bytes < 0)
{
if (errno == EINTR)
continue;
else
printf ("%Read error %s\n", pthread_self (),
strerror (errno));
}
}
if (0 == atoi (argv[4]))
{
printf ("doing close()....\n");
close (sockfd);
}
else if (1 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTRD)....\n");
shutdown (sockfd, SHUT_RD);
}
else if (2 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTWR)....\n");
shutdown (sockfd, SHUT_WR);
}
else if (3 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTRDWR)....\n");
shutdown (sockfd, SHUT_RDWR);
}
if (line)
free (line);
sleep (atoi (argv[5]));
}
void *
receiver (void *arg)
{
char buff[512];
int bytes;
while (1)
{
bytes = recv (sockfd, buff, sizeof (buff), 0);
if (bytes < 0)
{
if (errno == EINTR)
continue;
else
printf ("%Read error %s\n", pthread_self (),
strerror (errno));
pthread_exit (-1);
}
else if (bytes == 0)
{
printf ("connection closed by Peer\n");
close(sockfd);
pthread_exit (-1);
}
else
{
printf ("Msg Received:%s\n", buff);
}
}
}
Call shutdown(WR) will send FIN,but close have little different:if fd reference count not equal 0 will not send FIN.
you can use shutdown( socket, SHUT_WR) before close(socket)

Resources