I am implementing server client program where the both the ports user define
in server side user will insert server port number using command line interface
in client side user will insert client port id and then followed by serve port id.
I got stuck for a long time finding out what is wrong with my server client program. The issue is in binding though but I tried whatever possible way to implement it.
Server.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netdb.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
void error(char *msg){
perror(msg);
exit(1);
}
int main(int argc, char *argv[]){
int sockfd, newsockfd, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if(argc < 2){
fprintf(stderr,"error!!! no port provided\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(atoi(argv[1]));
if ((bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
listen(sockfd, 5);
while(1){
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if(newsockfd < 0){
error("ERROR on accept");
exit(1);
}
printf("New client connected from port no %d and IP %s\n", ntohs(cli_addr.sin_port), inet_ntoa(cli_addr.sin_addr));
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if(n < 0){
error("ERROR reading from socket");
exit(1);
}
}
printf("Here is the message: %s \n",buffer);
n = write(newsockfd, "I got your message", 18);
if(n < 0){
error("ERROR writing from socket");
exit(1);
}
return (0);
}
Client.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netdb.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
void error(char *msg){
perror(msg);
exit(1);
}
int main(int argc, char *argv[]){
int sockfd, n;
struct sockaddr_in serv_addr;
char buffer[256];
if(argc < 3){
fprintf(stderr,"usage %s hostname port\n",argv[0]);
exit(0);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
error("ERROR opening socket");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2]));
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
error("ERROR connecting");
exit(1);
}
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 256, stdin);
n = write(sockfd, buffer, strlen(buffer));
if(n < 0){
error("ERROR writing to socket");
exit(1);
}
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if(n < 0){
error("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
return (0);
}
Terminal where client is running
Terminal where server is running.
The server never creates a socket. sockfd is an uninitialized, indeterminate value when passed to bind.
Turning up your compiler's warning level may have alerted you to this:
server.c:36:14: warning: ‘sockfd’ may be used uninitialized [-Wmaybe-uninitialized]
36 | if ((bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) != 0) {
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Obtain a valid file descriptor before trying to bind.
if (-1 == (sockfd = socket(...)) {
perror("socket");
return 1;
}
Consider the use of getaddrinfo to establish your sockets. The man page as well as Beej's Guide to Network Programming have various examples.
Additionally, the code that responds to the client
printf("Here is the message: %s \n",buffer);
n = write(newsockfd, "I got your message", 18);
if(n < 0){
error("ERROR writing from socket");
exit(1);
}
is outside of the loop that handles incoming connections.
Related
Basically, I am doing a tcp project in c and I made it so multiple clients can connect to my server by using fork. In my server I have a linked list structure that keeps data that clients are sending. However, when I am sending data from the client to the linked list located in the server, the server creates a new linked list for that client . Instead of adding all client data to the same linked list. I know for certain its not a problem with the linked list. Fork() duplicates the process, so after calling fork there are actually 2 instances of my program running. So yeah I realized the clients aren't communicating with the same server? How should I fix this problem? Do I get rid of fork? Please conceptually explain to me what I must do. I'm not posting my actual code because it is sensitive . But here is basically what I am doing:
server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void dostuff(int); /* function prototype */
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen, pid;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
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");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
return 0; /* we never get here */
}
void dostuff (int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
client :
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
Because fork() creates a new process, you will need to use shared memory (shm_open(), shm_unlink(), mmap(),...). You can find based on this other question's answer.
You can get rid of fork and instead
a thread for each connection, which means you can share state between clients in your program. This will however require you to add synchronization (mutexes, etc.) around all shared data.
use a single thread in asynchronous/nonblocking mode (select/epoll/etc.) to serve all clients.
I have written a client code to create a socket and send a request to the client and as HTTP 1.1 uses Connection:Alive by default still the connection closes.How can i create a persistent connection such that the server listens to every request until the connection is closed.The client side code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(char *msg){
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n,i;
int Max_Requests;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
Max_Requests=atoi(argv[3]);
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
i=0;
while(i<Max_Requests){
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
i++;
}
return 0;
}
The problem is your use of fgets to read input from the user to form the request.
The problem with it is how you use it, namely to read a single line that you send to the server as the request. You then promptly go to the read call and wait for the response, without having sent the full request and its headers.
That will lead the server to time-out and close the connection, since it haven't received a full request.
My objective of my programs is to implement a proxy server that can be connected by a single client and would only allow http request.
The Requirements
To create a C based client-server architecture using sockets
The proxy server should be able to accept and service single client's http requests
Code
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if(argc < 3){
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd= socket(AF_INET, SOCK_STREAM, 0);
if(sockfd <0){
perror("ERROR opening Socket");
exit(1);
}
server= gethostbyname(argv[1]);
if(sockfd == NULL){
fprintf(stderr,"ERROR, no such host\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portnum);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0){
fprintf(stderr,"ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n=write(sockfd,buffer,strlen(buffer));
if(n<0){
printf("Error writing to socket");
exit(1);
}
bzero(buffer,256);
n=read(sockfd,buffer,255);
if(n<0){
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
Proxy server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[]){
int sockfd, newsockfd, portnum, clilen;
char buffer[256], hostname[256];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
if(argc < 2){
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0){
fprintf(stderr,"ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
fprintf(stderr,"ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0){
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if(newsockfd<0){
fprintf(stderr,"ERROR on accept\n");
exit(1);
}
pid=fork();
if(pid==0){
bzero(buffer, 256);
n= read(newsockfd, buffer, 255);
if(n<0){//message from client
fprintf(stderr,"ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname : %s\n", hostname);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[510];//sending to webserver
wbport =80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb <0){
printf("error opeing websocket\n");
exit(1);
}
wbhost= gethostbyname(hostname);
printf("%s", wbhost->h_name);
if(sockwb == -1){
printf("NO SUCH web HOST\n");
exit(1);
}
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr,
(char *)&webser_addr.sin_addr.s_addr,
wbhost->h_length);
webser_addr.sin_port = htons(wbport);
if(connect(sockwb,(struct sockaddr *)&webser_addr,sizeof(webser_addr)) < 0){
printf("error on web connecting\n");
exit(1);
}
bzero(webbuf,510);
strcpy(webbuf, "GET http://");
strcat(webbuf, hostname);
strcat(webbuf, " HTTP/1.1");
printf("%s\n", webbuf);
x=write(sockwb,webbuf,strlen(webbuf));
if(x<0){
printf("error writing to web sock");
exit(1);
}
bzero(webbuf,510);
x=read(sockwb,webbuf,510);
if(n<0){
printf("error reading from web socket");
exit(1);
}
n = write(newsockfd, webbuf,255 );//write back to client
if (n<0){
fprintf(stderr,"ERROR WRITING to socket");
exit(1);
}
printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
I have been able to implement a simple client-server exchange with sockets, my issue is with the Http request. I do have to access the web server through port 80 using the GET Method.
The way i have the input that the client is sending to the proxy server should be : www.NAME.com
The server doesn't seem to doing anything after the initial connection to the client.
As usual, null-terminated strings are not managed properly here. When following construct is used
send(sock, buff, strlen(buf));
The trailing null-terminated character is not sent. On the receiving side, there are two problems. First, recv(sock, buff, sizeof(buff)); can receive unpredictable amount of bytes - from 1 to the size of the string provided. So you need to read until you read all the message. Here comes the dilemma - how do you know how long is the actual message? The answer is that you either agree on the size of all the strings in advance, and than you always send that many bytes (regardless of actual string length) or you prefix the the string with it's size in the message. The second problem is that even if by luck the whole string is read, it is not null-terminated, and as such, unusable in the program. It has be null-terminated manually.
I'm writing a two way chat in C, but what I'd really like to do is have the chat server print the ip of the host when it starts up. My code thus far looks like this:
#include<stdio.h> //printf
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define PORT 8888 //The port on which to listen for incoming data
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(void)
{
struct sockaddr_in serv_addr, cli_addr;
int sockfd, newsockfd, n;
socklen_t cli_len;
char buffer[512];
char message[512];
//create a socket
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR OPENING SOCKET");
// zero out the structure
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
//bind socket to port
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR ON BINDING");
//keep listening for data
//inet_ntoa(serv_addr.sin_addr)
inet_ntop(AF_INET, &serv_addr.sin_addr.s_addr, buffer, sizeof(serv_addr));
listen(sockfd,5);
printf("Listening on ip %s and port %d\n", buffer, ntohs(serv_addr.sin_port));
while(1)
{
cli_len = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
if (newsockfd < 0) error("ERROR ON ACCEPT");
while(1)
{
bzero(buffer,512);
n = read(newsockfd,buffer,511);
if(n < 0) error("ERROR READING FROM SOCKET");
printf("Friend: %s\n" , buffer);
//now reply
printf("Please enter the message: ");
bzero(buffer,512);
fgets(buffer,511,stdin);
n = write(newsockfd,buffer, strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
}
close(sockfd);
return 0;
}
Currently when I make and run it immediately prints
Listening on ip 0.0.0.0 and port 8888
This really should be simple. I realize that it's binding to all interfaces, so it's accurate that 0.0.0.0 is the ip.
Is there any way to have it show a host ip? Am I looking at pinging the DNS to lookup ip by hostname and then print that? Any other suggestions?
Thanks
I found a solution. My code now looks like this:
#include<stdio.h> //printf
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#define PORT 8888 //The port on which to listen for incoming data
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(void)
{
struct sockaddr_in serv_addr, cli_addr;
int sockfd, newsockfd, n;
socklen_t cli_len;
char buffer[512];
char message[512];
char sZhostName[255];
gethostname(sZhostName,255);
struct hostent *host_entry;
host_entry = gethostbyname(sZhostName);
//create a socket
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR OPENING SOCKET");
// zero out the structure
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
//bind socket to port
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR ON BINDING");
//keep listening for data
listen(sockfd,5);
printf("Listening on ip %s and port %d\n", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list), ntohs(serv_addr.sin_port));
while(1)
{
cli_len = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
if (newsockfd < 0) error("ERROR ON ACCEPT");
while(1)
{
bzero(buffer,512);
n = read(newsockfd,buffer,511);
if(n < 0) error("ERROR READING FROM SOCKET");
printf("Friend: %s\n" , buffer);
//now reply
printf("Please enter the message: ");
bzero(buffer,512);
fgets(buffer,511,stdin);
n = write(newsockfd,buffer, strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
}
close(sockfd);
return 0;
}
I used this article: https://suite.io/guy-lecky-thompson/7sd21g
There are suggestions around that getaddrinfo() replaces the gethostname()/gethostbyname() method, including in the famous Beej's guide, but I have not found out how to do this yet.
I have the following code below for a client page and a server page, for which I want to send five messages from the client side to the server side (for this initial test, anyway). The code works fine if I don't put it in a loop, but then I can only send one message before both the client and server close. When I put the code in a loop, it seems to get stuck in some sort of deadlock. The results I get are below followed by the code. I've tried various changes and done extensive research but just can't make it work. Thanks in advance for any solutions offered.
Server side results
./server 5000
Here is the message: test
Client side results
./client localhost 5000
Please enter the message: test
I got your message
Please enter the message: another test
Please enter the message: test again
Please enter the message: test yet again
// The server stops acknowledging receipt of the message and I have to keep resetting both client and server
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
printf("Need at least two arguments\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("ERROR opening socket\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
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)
printf("ERROR on binding\n");
listen(sockfd,atoi(argv[1]));
clilen = sizeof(cli_addr);
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) printf("ERROR reading from socket\n");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0) printf("ERROR writing to socket\ns");
}
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
printf("Not enough arguments\n");
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("Error opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
printf("Error: no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
printf("Error connecting\n");
int i = 0;
while (i < 5) {
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
printf("Error writing to socket");
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if (n < 0)
printf("Error reading from socket");
printf("%s\n", buffer);
i++;
}
close(sockfd);
return 0;
}
You need to restructure your code to deal with the one connection you have before accepting another one. This is terrible code but is the basic template for what you want to do. Even so you can't deal with more than one connection at a time with this. You either have to multiplex or thread. Also, always read/write in a loop because you are not guaranteed to get a full request filled on any one call. Learn about and use perror or brothers.
void do_stuff(int sock)
{
for (int i = 0; i < 5; ++i)
{
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0)
printf("ERROR reading from socket\n");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message\n", 18);
if (n < 0)
printf("ERROR writing to socket\ns");
}
}
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0)
{
if (newsockfd < 0)
printf("ERROR on accept\n");
do_stuff(newsockfd);
close(newsockfd);
}
I know its too late. But for someone who might have the same doubt I am trying to answer this.
Answer
How about changing the server program to this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
printf("Need at least two arguments\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("ERROR opening socket\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
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)
printf("ERROR on binding\n");
listen(sockfd,atoi(argv[1]));
clilen = sizeof(cli_addr);
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
while(true)
{
n = read(newsockfd,buffer,255);
if (n < 0)
{
printf("ERROR reading from socket\n");
break;
}
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0)
{
printf("ERROR writing to socket\ns");
break;
}
}
close(newsockfd);
}
close(sockfd);
return 0;
}
This is the changed part. I changed the code slightly such that the connection will close if any write or read error occurs.
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
while(true)
{
n = read(newsockfd,buffer,255);
if (n < 0)
{
printf("ERROR reading from socket\n");
break;
}
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0)
{
printf("ERROR writing to socket\ns");
break;
}
}
close(newsockfd);
}