My question today is in regards to socket programming. I'm working on a program that creates a client and a server, where the client interacts with the records in the server database via given commands. I'm very new to socket programming, and i've been given some starter code to get the server and client connected and interacting. That being said, i'm very unfamiliar with which part of said code needs to be iterated in order to receive and send another message until the "stop" command is given. Until then, I want the user to continue to be able to send messages to the server.
(relevant) server code:
void error(char *msg)
{
perror(msg);
exit(1);
}
int main () {
int num = 1;
int del;
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/*STEP 1*********************************************/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*Make sure opening was successful*/
if (sockfd < 0)
error("ERROR opening socket");
/*STEP 2********************************************
0 out the server address*/
memset((char *) &serv_addr, 0, sizeof(serv_addr));
/*convert argument to int*/
portno = PORTNO;
/*this is always the same for this type of connection*/
serv_addr.sin_family = AF_INET;
/*INADDR_ANY is a macro that will find the current machine IP*/
serv_addr.sin_addr.s_addr = INADDR_ANY;
/*make sure byte order is correct
may be a no-op, but better safe than sorry*/
serv_addr.sin_port = htons(portno);
/*STEP 3********************************************/
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
error("ERROR on binding");
}
/*STEP 4********************************************
Open server up for listening, if you don't listen
you won't hear*/
listen(sockfd,5);
/*STEP 5******************************************/
clilen = sizeof(cli_addr);
/*Accept blocks until a connection with
a client is made. Returns a new socket
to communicate with the new connection.
Also receives address data about client*/
/*Communicate************************************/
char *array[20];
do {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
memset(buffer, 0, 256);
printf("%s", "Enter Message:");
n = read(newsockfd,buffer,255);
printf("I read %d\n",n);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
int i = 0;
char *p = strtok(buffer, " ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
if (strcmp(array[0], "put") == 0) {
insert(&front, array);
puts("PUT COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "lname") == 0) {
puts("GET LNAME COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "fname") == 0) {
puts("GET FNAME COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "SID") == 0) {
puts("GET SID COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "GPA") == 0) {
puts("GET GPA COMMAND");
} else if (strcmp(array[0], "delete") == 0 && strcmp(array[1], "SID") == 0) {
puts("DELETE COMMAND");
} else {
printf("%s\n", "Not a valid command.");
}
} while (strcmp(array[0], "stop") != 0);
return 0;
}
(relevant) client code:
#define PORTNO 20321
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
/*set up ints for socket file descriptor
port number and return of read/write*/
int sockfd, portno, n;
int i;
/*structure for server info*/
struct sockaddr_in serv_addr;
/*used to hold the return of the function
that finds our server address, will
be copied into serv_addr*/
struct hostent *server;
/*for our message*/
char buffer[256];
/*make sure usage is correct*/
if (argc < 2) {
fprintf(stderr,"usage %s hostname\n", argv[0]);
exit(0);
}
/*convert our port number*/
portno = PORTNO;
/*create the socket*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*make sure it was made*/
if (sockfd < 0)
error("ERROR opening socket");
/*gethostbyname takes our host domain name and
resolves it to an address, there is a similar
function, gethostbyaddr that takes an address
and returns the same struct, struct hostent*/
server = gethostbyname(argv[1]);
/*make sure the host exists*/
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
/*0 out the server address stuct and set members*/
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
/*copy the data returned from gethostbyname
into the server address struct*/
memcpy((char *)server->h_addr_list,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
/*Request a connection to the server through the socket we set up
make sure it connected, this function will also do the binding
of our socket and server info*/
if (connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0) {
error("ERROR connecting");
}
for (i = 0; i < 3; i++) {
printf("Choose an operation: \n 1. put ln,fn,mi,SID,GPA\n 2. get lname\n 3. get fname\n 4. get SID\n 5. get GPA\n 6. delete (SID)\n 7. stop\nChoice: ");
/*Retrieve a message to send from the user*/
memset(buffer, 0, 256);
fgets(buffer,255,stdin);
/*send the message to the socket*/
printf("length is %d\n", (int)strlen(buffer));
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
memset(buffer, 0, 256);
/*await an incoming message, read stops all process*/
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
}
My server seems to be waiting for messages correctly, as I can restart my client program and send another message while the server is waiting and it is received as usual. But the way it stands, it will ask for another message, but it doesn't get properly sent/received like the first one did. For now, I have it set to loop 3 times just as a test. How do I properly create this read/write loop to the server?
Assuming you only want to have a single connection at a time then this, untested, version of you while loop should work.
while (true)
{
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
while (true)
{
memset(buffer, 0, 256);
printf("%s", "Enter Message:");
n = read(newsockfd,buffer,255);
printf("I read %d\n",n);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
int i = 0;
char *p = strtok(buffer, " ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
if (strcmp(array[0], "put") == 0) {
insert(&front, array);
puts("PUT COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "lname") == 0) {
puts("GET LNAME COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "fname") == 0) {
puts("GET FNAME COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "SID") == 0) {
puts("GET SID COMMAND");
} else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "GPA") == 0) {
puts("GET GPA COMMAND");
} else if (strcmp(array[0], "delete") == 0 && strcmp(array[1], "SID") == 0) {
puts("DELETE COMMAND");
}
// Checking for stop command here
else if (strcmp(array[0], "stop") ==0)
{
close(newsockfd);
break;
}
else {
printf("%s\n", "Not a valid command.");
}
}
}
Related
I have a simple tcp client server program. Client sends text, server prints it ito terminal. I need to make it so client can connect to server by ip address, no just a port (i have it on localhost now). How can I do this? Tried many things, getting errors everytime.
Here's the client code:
int client(char * add) //add is an address passed, either hostname (for ex. google.com)
{ //or just a normal dotted ip (1.2.3.4)
int s, t, len;
struct sockaddr_un remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
int i=0;
while(fgets(str, 100, stdin)) {
if (send(s, str, strlen(str), 0) == -1) {
perror("send");
exit(1);
}
}
close(s);
return 0;
}
And tere's a server:
int server(void)
{
int s, s2, t, len;
int z;
struct sockaddr_un local, remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
for(;;) {
int done, n;
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *) &remote, (socklen_t *) &t)) == -1) {
perror("accept");
exit(1);
}
done = 0;
do {
n = recv(s2, str, 100, 0);
if (n <= 0) {
if (n < 0) perror("recv");
done = 1;
}
if (!done)
printf("%s", str);
fflush(stdout);
sleep(1);
} while (!done);
close(s2);
}
return 0;
}
Can I connect my client with that server using ip address?
My driver funtion chooses if I want to start a server or a client, it's all in one file.
To start a server i use:
./main.o -l [port]
and to start a client I'd want to use:
./main.o [address] [port]
I don't realy know how to translate the address and then use it to connect. I mean, I've tried gethostbyname(), but then I didn't know where tu put this address because sockaddr_un has no address field to fill.
I implemented a client server application in C, I created the admin client with different options, GET_NO_CLIENTS return number of clients connected, GET_CLIENTS must to return the clients id. Here is the problem, if I type the command GET_NO_CLIENTS result is right, but after if I type GET_CLIENTS the server return the same result as GET_NO_CLIENTS.
Here is my code for client:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.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) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
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);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
while(1)
{
char admin[2000] = "aDmIn007BO$$_";
printf("Please enter the message: ");
fgets(buffer, 256, stdin);
strcat(admin, buffer);
/* Send message to the server */
n = write(sockfd, admin, strlen(admin));
memset(buffer, '\0', sizeof(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
//bzero(admin, 256);
n = read(sockfd, buffer, 256);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
else
{
puts(buffer);
memset(buffer, '\0', 256);
}
memset(admin, '\0', sizeof(admin));
}
return 0;
}
The server code:
/*
C socket server example, handles multiple clients using threads
*/
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
pthread_t tid;
int count_conn = 0, nr_admin = 0;
int clients_id[50];
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
// printf("!!!!!!!%s", server.sin_addr.s_addr);
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
count_conn++;
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( sniffer_thread , NULL);
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int connfd = 0;
int read_size;
int err;
int i = 0, j = 0;
char *message , client_message[2000], file_name[2000], send_buffer[130000], command[200];
int kk = 0;
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
clients_id[kk] = sock;
//Send the message back to client
if(strncmp(client_message, "GET_FILE ", 8) == 0)
{
for(i = 9; i < strlen(client_message); i++){
file_name[j] = client_message[i];
j++;
}
printf("Connection accepted and id: %d\n", sock);
printf("Connected to Client: %s:%d\n", "127.0.0.1", 8888);
FILE *fp = fopen(file_name,"rb");
if(fp == NULL)
{
perror("File");
}
int bytes_read = fread(send_buffer, sizeof(char), sizeof(send_buffer), fp);
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0)
{
perror("ERROR reading from file");
}
//send file size to client
write(sock, &bytes_read, sizeof(int));
void *p = send_buffer;
while (bytes_read > 0)
{
int bytes_written = write(sock, send_buffer, bytes_read);
if (bytes_written <= 0)
{
perror("ERROR writing to socket\n");
}
bytes_read -= bytes_written;
p += bytes_written;
}
printf("Done Sending the File!\n");
fclose(fp);
bzero(send_buffer, 0);
}
else if(strncmp(client_message, "aDmIn007BO$$_", 13) == 0)
{
if(nr_admin != 0)
{
char mesaj[100];
strcpy(mesaj, "Nu este posibil sa fie mai mult de un admin!");
write(sock, mesaj, strlen(mesaj));
}
else
{
nr_admin++;
for(i = 13; i < strlen(client_message); i++)
{
command[j] = client_message[i];
j++;
}
if(strncmp(command, "GET_NO_CLIENTS", 14) == 0)
{
char str1[15];
sprintf(str1, "%d", count_conn);
write(sock , str1, sizeof(char));
memset(str1, '\0', sizeof(str1));
}
else if(strncmp(command, "GET_CLIENTS", 11) == 0)
{
char str[15];
int i = 0;
for(i = 0; i < strlen(clients_id); i++)
{
sprintf(str[i], "%d", clients_id[i]);
puts(str[i]);
}
write(sock, str, strlen(str));
memset(str, '\0', sizeof(str));
}
nr_admin--;
}
}
else
{
write(sock , client_message , strlen(client_message));
}
memset(client_message, '\0', sizeof(client_message));
memset(file_name, '\0', sizeof(file_name));
kk++;
}
if(read_size == 0)
{
puts("Client disconnected");
count_conn--;
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
Thanks for your help!
the problem is in this part:
for(i = 13; i < strlen(client_message); i++)
{
// command keeps getting appended because of j not being zeroed
command[j] = client_message[i];
j++; // this is not local variable for this for-loop
}
and moreover this thing doesn't seem to be right
sprintf(str[i], "%d", clients_id[i]);
instead you should do str[i] = clients_id[i];
And yes be careful with i
i have an infinite loop problem while im trying to send some messages from client to the server. Client has some commands like login, getusers, alias etc. and i want to check them into server. Here its my code.
CLIENT
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h> // for inet_addr
#include <string.h>
#include <zconf.h>
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in server;
char message[2000], server_reply[2000];
//Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("Could not create socket");
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//Connect to remote server
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
perror("Connect failed. Error");
return 1;
}
puts("Connected to server\n");
//keep communicating with server
while (1) {
printf("> ");
scanf("%[^\n]s", message);
fflush(stdin);
//Send some data
if (send(sock, message, strlen(message), 0) < 0) {
puts("Send failed");
return 1;
}
//Receive a reply from the server
if (recv(sock, server_reply, 2000, 0) < 0) {
puts("recv failed");
break;
}
printf("Server's reply : %s ", server_reply);
}
close(sock);
return 0;
}
SERVER
#include<stdio.h>
#include<string.h> // for strlen
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h> // for inet_addr
#include<unistd.h> // for write
#include<pthread.h> // for threading, link with lpthread
#include "server.h"
#include "split.h"
#define MAX_CLIENT_NUMBER 100
void *connection_handler(void *);
struct User {
char userName[10];
int clientSocketNo;
};
struct User users[MAX_CLIENT_NUMBER];
void getUsers() {
printf("Number %d",userArrayIndex);
for (int i = 0; i < userArrayIndex; ++i) {
printf("%s\n", users[i].userName);
}
}
void addUserToArray(char userName[10], int socketNumber) {
printf("Client logged in as %s\n", userName);
strcpy(users[userArrayIndex].userName, userName);
users[userArrayIndex].clientSocketNo = socketNumber;
userArrayIndex++;
}
void loginUser(char userName[10], int socketNumber) {
char *message = "login successful";
write(socketNumber, message, strlen(message));
addUserToArray(userName, socketNumber);
}
void *connection_handler(void *socket_desc) {
//Get the socket descriptor
char receivedMessage[2000]; //client's message
int readControl;
int sock = *((int *) socket_desc);
while ((readControl = recv(sock, receivedMessage, 2000, 0)) > 0) {
char **parsedCommand = malloc(100); //parsedClientMessage
parsing(parsedCommand, receivedMessage, " ");
printf("MESSAGE %s\n",parsedCommand[0]);
if (strcmp(parsedCommand[0], "login") == 0) {
loginUser(parsedCommand[1], sock);
}
if (strcmp(parsedCommand[0], "getusers") == 0) {
getUsers();
}
if (strcmp(parsedCommand[0], "exit") == 0) {
close(sock);
return 0;
}
}
if (readControl == 0) {
puts("Client disconnected");
clientNumber--;
fflush(stdout);
} else if (readControl == -1) {
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
int main(int argc, char *argv[]) {
int socket_desc, new_socket, c, *new_sock;
struct sockaddr_in server, client;
//Create Socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
puts("Could not create socket");
return 1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
puts("Binding failed");
return 1;
}
listen(socket_desc, 3);
puts("Server started");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) &c)) &&
clientNumber < MAX_CLIENT_NUMBER) {
pthread_t sniffer_thread/*[MAX_CLIENT_NUMBER]*/;
new_sock = malloc(1);
*new_sock = new_socket;
if (pthread_create(&sniffer_thread/*[clientNumber]*/, NULL, connection_handler,
(void *) new_sock) < 0) {
perror("Could not create thread");
return 1;
} else {
clientNumber++;
}
puts("Client connected");
}
if (new_socket < 0) {
perror("accept failed");
return 1;
}
return 0;
}
Its not full of my code but i think our problem in these parts. I dont understand why it happens. When i insert a break command into connection_handler's while loop, i cant send commands to the server anymore. Thanks...
I solved it. when i malloc the messages or replies, i give +1 to strlen(messsage).
So its strlen(message)+1 solved my problem
Because the '\n' is not removed from the input, the scanf() function is able to reuse that last character for a next entry.
The easiest solution to solve that problem is to clear the input
buffer fflush(stdin);.
while (1) {
printf("> ");
scanf("%[^\n]s", message);
fflush(stdin); // to clear \n from the buffer
//Send some data
if (send(sock, message, strlen(message), 0) < 0) {
I'm trying to write a program in TCP where both client and server side are able to communicate until either one sends quit, which terminates the connection. Right now, the client side is able to send stuff, but when the server side sends something, there is a seg fault on the client side. Apologies in advance if my code in not up to par as I am fairly new to coding. Any help would be greatly appreciated
here is my code:
//Client side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5432
#define MAX_LINE 256
int main(int argc, char * argv[])
{
struct hostent *hp;
struct sockaddr_in serv_addr;
char *host;
char buf[MAX_LINE];
int n, size;
int sockfd;
if (argc == 2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "error: can't find such host: %s\n", host);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)hp->h_addr,(char *)&serv_addr.sin_addr.s_addr,hp->h_length);
serv_addr.sin_port = htons(SERVER_PORT);
size = sizeof(serv_addr);
//active open
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd <0) {
error("ERROR opening socket");
exit(1);
}
printf("successfully opened socket\n");
int quit = 1;
while(quit == 1)
{
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR: could not connect\n");
close(sockfd);
exit(1);
}
fgets(buf, sizeof(buf), stdin);
if(strcmp(buf, "quit\n") == 0)
{
quit = 0;
int send;
send = sendto(sockfd, buf, MAX_LINE, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (send < 0)
error("ERROR: couldn't send data\n");
break;
}
int send;
send = sendto(sockfd, buf, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (send < 0)
error("ERROR: couldn't send data to server\n");
//receive data from server
send = recvfrom(sockfd, buf, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if(send < 0)
error("ERROR: couldn't receive from socket\n");
if(strcmp(buf, "quit\n") == 0)
quit = 0;
else
fputs(buf, stdout); //print what is received
}
}
This is the server side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAX_LINE 1024
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int clilen;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
portno = atoi(argv[1]);
//create a socket
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(portno);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
clilen = sizeof(serv_addr);
if (sockfd < 0)
{
error("ERROR opening socket");
}
//bind address to socket
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR: could not bind");
//listen for connection request
listen(sockfd,5);
int quit = 1;
while(quit == 1)
{
if((newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen))<0)
{
perror("Error: could no accept connection");
exit(1);
}
int n = recvfrom(newsockfd, buffer, MAX_LINE,0,(struct sockaddr *) &serv_addr,&clilen);
if(strcmp(buffer, "quit\n")== 0)
{
quit = 0;
break;
}
else
fputs(buffer, stdout);
//get data to be sent
fgets(buffer, MAX_LINE,stdin);
if(strcmp(buffer, "quit\n") == 0) //if quit is entered, terminate conn
{
quit = 0;
int n;
n = sendto(newsockfd, buffer, MAX_LINE,0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (n<0)
error("ERROR: could not send data");
break;
}
//send data
n = sendto(newsockfd, buffer, MAX_LINE, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (n<0)
error("ERROR sending data");
}
}
#user58697 is correct as to the proximate cause: last argument to sendto/recvfrom must be a pointer. However, I would add an additional note.
There's no point in using recvfrom/sendto in this program. You have a connected TCP socket; hence there's no reason to provide the sockaddr argument in each call. The addresses won't change, and you already know what they are (i.e. client knows its own address and specifies the address of the sender in the connect; server knows its own address and receives the client's address in the accept).
So once the connection is made, use the simpler send and recv functions instead. This will simplify your code and should simultaneously fix the problem.
You are making some big mistakes with this code, on both sides. Mostly bad socket management and bad buffer management. Try something more like this instead:
//Client side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5432
#define MAX_LINE 256
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char * argv[])
{
struct hostent *hp;
struct sockaddr_in serv_addr;
char *host;
char buf[MAX_LINE];
int sockfd, n;
if (argc != 2)
{
fputs("usage: simplex-talk host\n", stderr);
exit(1);
}
host = argv[1];
hp = gethostbyname(host);
if (!hp)
{
fprintf(stderr, "error: can't find such host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET)
{
fprintf(stderr, "error: host does not have an IPv4 address: %s\n", host);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)hp->h_addr, (char *)&serv_addr.sin_addr.s_addr, hp->h_length);
serv_addr.sin_port = htons(SERVER_PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR creating socket");
printf("successfully created socket\n");
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fputs("ERROR: could not connect\n", stderr);
close(sockfd);
exit(1);
}
printf("successfully connected to server\n");
int quit = 0;
while (quit == 0)
{
fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "quit\n") == 0)
{
quit = 1;
n = send(sockfd, buf, strlen(buf), 0);
if (n < 0)
fputs("ERROR: couldn't send data to server\n", stderr);
break;
}
n = send(sockfd, buf, strlen(buf), 0);
if (n < 0)
{
fputs("ERROR: couldn't send data to server\n", stderr);
break;
}
//receive data from server
n = recv(sockfd, buf, sizeof(buf)-1, 0);
if (n < 0)
{
fputs("ERROR: couldn't receive from server\n", stderr);
break;
}
if (n == 0)
{
printf("server disconnected\n");
break;
}
buf[n] = 0;
if (strcmp(buf, "quit\n") == 0)
quit = 1;
else
fputs(buf, stdout); //print what is received
}
close(sockfd);
return 0;
}
// Server side:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define MAX_LINE 256
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, clisockfd, portno, n;
char buffer[MAX_LINE];
struct sockaddr_in serv_addr, cli_addr;
int clilen;
if (argc < 2)
error("ERROR, no port provided");
portno = atoi(argv[1]);
//create a socket
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(portno);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR creating socket");
//bind address to socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR: could not bind socket");
//listen for connection request
if (listen(sockfd, 5) < 0)
error("ERROR: could not listen on socket");
int quit = 0;
while (quit == 0)
{
clilen = sizeof(serv_addr);
clisockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (clisockfd < 0)
error("ERROR: could not accept connection");
while (quit == 0)
{
n = recv(clisockfd, buffer, sizeof(buffer)-1, 0);
if (n < 0)
{
fputs("ERROR: couldn't receive from client\n", stderr);
break;
}
if (n == 0)
{
printf("client disconnected\n");
break;
}
buffer[n] = 0;
if (strcmp(buffer, "quit\n") == 0)
{
quit = 1;
break;
}
fputs(buffer, stdout);
//get data to be sent
fgets(buffer, sizeof(buffer), stdin);
if (strcmp(buffer, "quit\n") == 0) //if quit is entered, terminate conn
{
quit = 1;
n = send(clisockfd, buffer, strlen(buffer), 0);
if (n < 0)
fputs("ERROR: could not send data to client\n", stderr);
break;
}
//send data
n = send(clisockfd, buffer, strlen(buffer)-1, 0);
if (n < 0)
{
fputs("ERROR sending data to client\n", stderr);
break;
}
}
close(clisockfd);
}
close(sockfd);
return 0;
}
Now, with that said, do note that TCP is a streaming transport. There is no 1-to-1 relationship between send() and recv() and no concept of messages, like this code assumes. The sender could send a message like "hello joe\n" and the receiver could read like "hello" " joe" "\n", depending on how TCP decides to break of the data during transmission. You really need to take that into account. Read raw bytes and append them to the end of a buffer. Check the buffer for a message terminator (in this case, \n). If found, process that complete message and remove it from the buffer. Repeat until there are no more terminators found in the buffer. Leaving unprocessed data in the buffer so it can be completed by subsequent reads.
I'll leave this as an exercise for you.
I have the following C server and client:
SERVER
int main(int argc, char **argv) {
int listenfd, connfd, n;
struct sockaddr_in servaddr;
char recvline[1025];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket Error");
exit(1);
}
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(1024);
if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("Bind Error");
exit(1);
}
if (listen(listenfd, 1024) < 0) {
perror("Listen Error");
exit(1);
}
while(1) {
printf("Waiting connection...\n");
if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) {
perror("Accept Error");
exit(1);
}
printf("Waiting for input.\n");
while ((n = read(listenfd, recvline, sizeof(recvline))) > 0) {
recvline[n] = '\0';
if (fputs(recvline, stdout) == EOF) {
fprintf(stderr,"fputs Error\n");
exit(1);
}
}
printf("Read string: %s", recvline);
close(connfd);
}
}
CLIENT
int main(int argc, char **argv) {
int sockfd, connfd, n;
struct sockaddr_in servaddr;
char buff[1025], matricola[15];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket Error");
exit(1);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(1024);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
fprintf(stderr,"inet_pton Error for %s\n", argv[1]);
exit (1);
}
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
fprintf(stderr,"Connect Error\n");
exit(1);
}
printf("Matricola: ");
fflush(stdin);
scanf("%s", matricola);
strcpy(buff, matricola);
if (write(sockfd, buff, strlen(buff)) != strlen(buff)) {
perror("Write Error");
exit(1);
}
close(connfd);
}
I'm under Linux, I can start the server correctly from terminal that starts listening, but when I open another terminal instance and start the client, the server automatically executes the rest of the code and prints Read string: ### (random characters like dirty buffer). Is this because the server is not waiting for the client to write? What am I doing wrong in this code?
What I tought was that the server didn't wait for the client to write something, so I tried to add a sleep(10) before the server's read command, but nothing changes.
EDIT: I edited the read function from
n = read(listenfd, recvline, strlen(recvline) + 1)) > 0
to
n = read(listenfd, recvline, sizeof(recvline))) > 0
But still it doesn't fix the issue.
Change your inner while cycle to read from the connected file descriptor, not the listening file descriptor, like this:
while ((n = read(connfd, recvline, strlen(recvline) + 1)) > 0) {
recvline[n] = '\0';
if (fputs(recvline, stdout) == EOF) {
fprintf(stderr,"fputs Error\n");
exit(1);
}
}
This line
while ((n = read(listenfd, recvline, sizeof(recvline))) > 0) {
tries to read from the listening socket. This does not make sense.
You need to read from the accepted socket. So it should be:
while ((n = read(connfd, recvline, sizeof(recvline))) > 0) {
Moreover it should be
while ((n = read(connfd, recvline, sizeof(recvline) - 1)) > 0) {
as after the read() you do
recvline[n] = '\0';
For the OP's source if you'd have read sizeof recvline bytes recvline[n] would address one behind the last element of recvline.