Multiclient and server commandline argument issues - c

I have code for a server that can handle multiple clients. The client program can connect to the server and issue Unix commands such as ls, date, clear, etc. I have two problems that I cannot figure out. 1) When I initially type ls as an argument it will return some weird garbage, and then if I do ls again then it starts working properly. So only in the beginning, it will give me garbage. 2) When I type the argument 'ps -ael' into the terminal, it will work properly, but then after that I get a 'Failed' message, which is coming from the Client code, specifically at the while(1) loop where if (send(clientSocket, s, echolen, 0) != echolen), this is where the error is occurring. I was curious to know if someone could point to what the problem could be, I think it might be because I create a char array that's too big but I'm not sure.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
int main(int argc, char *argv[]){
int clientSocket, ret, portnum;
struct sockaddr_in serverAddr;
int received = 0;
unsigned int echolen;
char buffer[1024];
if(argc < 3){
fprintf(stderr,"usage %s <server-ip-addr> <server-port>\n", argv[0]);
exit(0);
}
portnum = atoi(argv[2]);
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Client Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
// memset(&buffer, '\0', sizeof(buffer));
// serverAddr.sin_family = AF_INET;
// serverAddr.sin_port = htons(PORT);
// serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// bzero((char *) &serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
if(!inet_aton(argv[1], &serverAddr.sin_addr)){
fprintf(stderr, "Error invalid server IP address\n");
exit(1);
}
serverAddr.sin_port = htons(portnum);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Connected to server.\n");
char s[100];
while(1){
fgets(s, 100, stdin);
s[strlen(s)-1]='\0';
echolen = strlen(s);
/* send() from client; */
if (send(clientSocket, s, echolen, 0) != echolen)
{
printf("Failed");
}
if(strcmp(s,"exit") == 0) // check if exit is typed
exit(0);
fprintf(stdout, "Message from server: ");
while (received < echolen)
{
int bytes = 0;
/* recv() from server; */
if ((bytes = recv(clientSocket, buffer, echolen, 0)) < 1)
{
printf("Failed to get Information");
}
received += bytes;
buffer[bytes] = '\0';
fprintf(stdout, buffer);
}
int bytes = 0;
do {
buffer[bytes] = '\0';
printf("%s\n", buffer);
} while((bytes = recv(clientSocket, buffer, BUFFSIZE-1, 0))>=BUFFSIZE-1);
buffer[bytes] = '\0';
printf("%s\n", buffer);
printf("\n");
}
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
#define MAX 2048
void setup(char inputBuffer[], char *args[], int *background){
const char s[4] = " \t\n";
char *token;
token = strtok(inputBuffer, s);
int i = 0;
while(token != NULL){
args[i] = token;
i++;
token = strtok(NULL, s);
}
args[i] = NULL;
}
void HandleClient(int sock){
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
memset(data, 0, MAX);
while(1){
data[0] = '\0';
if((received = recv(sock, buffer, BUFFSIZE, 0)) < 0){
printf("Error");
}
buffer[received] = '\0';
strcat(data, buffer);
if(strcmp(data, "exit") == 0){
exit(0);
}
puts(data);
char *args[100];
setup(data, args, 0);
int pipefd[2], length;
if(pipe(pipefd)){
printf("failed to create pipe");
}
pid_t pid = fork();
char path[MAX];
if(pid==0)
{
close(pipefd[0]); // close the readonly side of the pipe
//close(1); // close the original stdout
dup2(pipefd[1],1); // duplicate pipfd[1] to stdout
dup2(pipefd[1], fileno(stderr));
//close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
printf("before execvp");
execvp(args[0],args); // finally execute the command
// exit(0);
}
else
if(pid>0)
{
close(pipefd[1]);
memset(path,'\0',MAX);
while(length=read(pipefd[0],path,MAX-1)){
//printf("Data read so far %s\n", path);
if(send(sock,path,strlen(path),0) != strlen(path) ){
printf("Failed");
}
fflush(NULL);
//printf("Data sent so far %s\n", path);
memset(path,0,MAX);
}
close(pipefd[0]);
//exit(1); removed so server will not terminate
}
else
{
printf("Error !\n");
exit(0);//
}
}
}
int main(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding");
exit(1);
}
printf("Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("Listening....\n");
}else{
printf("Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*) &newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
//worker
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, ":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
printf("Client: %s\n", buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
HandleClient(newSocket);
}
}
}
close(newSocket);
return 0;
}

Related

Communication between containers on Docker

I have 3 services in C and I want they communicate toghether with a docker compose but I can't.
I tried with a two simples images and they connected but not in a docker compose.
The problem are the function connect(). He return -1 beaucause in the inet_addr(), I want to include the image who the message will be sent.
I use 3 images with gcc for to compile C files.
# FILE : service1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
//#define PORT_SERV 4443
#define PORT_CLI 4443
time_t t;
static void * client(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[256];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket < 0) {
printf("[Client -] Error in Client Socket \n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_CLI);
serverAddr.sin_addr.s_addr = inet_addr("image1");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
while (ret < 0) {
printf("[Client -] Erreur de connexion. Nouvel essai ! %d\n", ret);
fflush(stdout);
sleep(3);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
}
printf("[Client +] Connected to Server.\n");
fflush(stdout);
while(1){
time(&t);
strcpy(buffer, "Bonjour depuis le service 1");
sleep(5);
send(clientSocket, buffer, strlen(buffer), 0);
if (strcmp(buffer, ": exit") == 0) {
printf("[Client -] Disconnected from server.\n");
fflush(stdout);
exit(1);
}
if (recv(clientSocket, buffer, 256, 0) < 0) {
printf("[Client -] Error in receiving data. \n");
fflush(stdout);
} else {
printf("%sService 1 : %s \n", ctime(&t), buffer);
fflush(stdout);
}
}
}
int main(void){
//pthread_t s,
pthread_t c;
int ret = 0;
ret = pthread_create(&c, NULL, &client, NULL);
/*ret = pthread_create(&s, NULL, &server, NULL);
if (! ret) {
ret = pthread_create(&c, NULL, &client, NULL);
}*/
//pthread_join(s, NULL);
pthread_join(c, NULL);
return 0;
}
FILE = service2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT_SERV 4442
#define PORT_CLI 4443
time_t t;
time_t t2;
static void * server(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
char buffer[256];
pid_t childpid;
socklen_t addr_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("[-] Error in Client Socket\n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_SERV);
serverAddr.sin_addr.s_addr = inet_addr("image1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (ret < 0) {
printf("[-] Error in binding\n");
fflush(stdout);
exit(1);
}
printf("[+] Bind to port %d\n", PORT_CLI);
fflush(stdout);
if (listen(sockfd, 10) == 0) {
printf("[+] Listening...\n");
fflush(stdout);
} else {
printf("[-] Error in binding\n");
fflush(stdout);
}
while(1)
{
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0) {
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
if ((childpid = fork()) == 0)
{
close(sockfd);
while (1)
{
time(&t2);
recv(newSocket, buffer, 256, 0);
if(strcmp(buffer, ": exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
break;
} else {
printf("%sClient : %s\n", ctime(&t2), buffer);
fflush(stdout);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
}
static void * client(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[256];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket < 0) {
printf("[-] Error in connection\n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_CLI);
serverAddr.sin_addr.s_addr = inet_addr("image3");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
while (ret < 0) {
printf("[-] Erreur de connexion. Nouvelle tentative !\n");
fflush(stdout);
sleep(3);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
}
printf("[+] Connected to Server.\n");
while(1){
time(&t);
strcpy(buffer, "Bonjour depuis le service 2");
sleep(5);
send(clientSocket, buffer, strlen(buffer), 0);
if (strcmp(buffer, ": exit") == 0) {
printf("[Client -] Disconnected from server.\n");
fflush(stdout);
exit(1);
}
if (recv(clientSocket, buffer, 256, 0) < 0) {
printf("[Client -] Error in receiving data. \n");
fflush(stdout);
} else {
printf("%sService 2: %s \n", ctime(&t), buffer);
fflush(stdout);
}
}
}
int main(void){
pthread_t s, c;
int ret = 0;
ret = pthread_create(&s, NULL, &server, NULL);
if (! ret) {
ret = pthread_create(&c, NULL, &client, NULL);
}
pthread_join(s, NULL);
pthread_join(c, NULL);
return 0;
}
FILE = service3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT_SERV 4444
//#define PORT_CLI 4443
time_t t;
time_t t2;
static void * server(){
printf("Hello World!\n");
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
char buffer[256];
pid_t childpid;
socklen_t addr_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("[-] Error in connection\n");
exit(1);
}
printf("[+] Client Socket is created !\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_SERV);
serverAddr.sin_addr.s_addr = inet_addr("image2");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (ret < 0) {
printf("[-] Error in binding\n");
exit(1);
}
printf("[+] Bind to port %d\n", 4444);
if (listen(sockfd, 10) == 0) {
printf("[+] Listening...\n");
} else {
printf("[-] Error in binding\n");
}
while(1)
{
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0) {
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
if ((childpid = fork()) == 0)
{
close(sockfd);
while (1)
{
time(&t2);
recv(newSocket, buffer, 256, 0);
if(strcmp(buffer, ": exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
} else {
printf("%sClient : %s\n", ctime(&t2), buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
}
int main(void){
printf("Hello World!\n");
fflush(stdout);
pthread_t s;
//pthread_t c;
int ret = 0;
printf("Thread du server\n");
ret = pthread_create(&s, NULL, &server, NULL);
/*if (! ret) {
printf("Thread du client\n");
ret = pthread_create(&c, NULL, &client, NULL);
}*/
pthread_join(s, NULL);
//pthread_join(c, NULL);
return 0;
}
File = docker-compose.yml
version: "3.8"
services:
image1:
build: ./image1
image: service1:1.0
networks:
- mynet
ports:
- 127.0.0.1:4441:4441
image2:
build: ./image2
image: service2:1.0
networks:
- mynet
ports:
- 127.0.0.1:4442:4442
image3:
build: ./image3
image: service3:1.0
networks:
- mynet
ports:
- 127.0.0.1:4443:4443
networks:
mynet:
I build and run with docker compose build docker compose up -d and the images don't connect toghether.
Thanks !

communication between client and server,executiolg commands

I am trying to do a command line, based on socket communication.My only problem is that after exexvp is executed (and the data are being printed on the client's side), the client close and i want to keep him alive.
This is my code:
client.c
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#define PORT_NUMBER 1754
#define HOST_NUMBER
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, port_number, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
//fprintf(stderr, "usage %s hostname port\n", argv[0]);
//first parameter is ip address
printf("usage %s hostname port\n", argv[0]);
exit(0);
}
port_number = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0 )
error("ERROR opening socket!Socket failed!");
printf("Trying to connect...\n");
server = gethostbyname(argv[1]); //ip address
if (server == NULL) {
error( "ERROR, no such host");
//fprintf(stderr, "ERROR, no such host\n"); exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; //AF_UNIX
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(port_number);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Connected!\n");
printf("%s_>\n",argv[1]);
while(1) {
printf("Please enter the message: "); //THE CLIENT MUST WRITE A COMMAND
fgets(buffer, 256, stdin); //apo stdin sto buffer
n = write(sockfd, buffer, strlen(buffer)); //apo buffer sto socket
if(n < 0 ) {
error("ERROR writing to socket");
}
bzero(buffer, 256);
if ( recv(sockfd, buffer, 256, 0) < 0) {
printf("Server closed connection\n");
}
printf("%s\n", buffer);
}
return 0;
}
sever.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
void parse(char *vector_args[20], char *buffer){
buffer[strcspn(buffer, "\n")] =0;
int i=0;
char * pch;
pch = strtok (buffer," ");
while (pch != NULL )
{
vector_args[i]=pch;
printf (" %s\n",pch);
pch = strtok (NULL, " ");
i++;
}
vector_args[i]=NULL;
int k=0;
for(k=0; k<=i; k++) {
printf("vector %d = %s \n",k,vector_args[k]);
}
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
char str[INET_ADDRSTRLEN];
char *vector_args[20];
int status;
char *fd[2];
if (argc < 2)
{
fprintf(stderr, "No port provided\n");
exit(1);
}
unlink("sockfd"); //remove any old socket
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");
int l = listen(sockfd, 5);
if (l < 0)
{
error("listen failed!");
}
clilen = sizeof(cli_addr);
printf( "Server waiting for a connection...\n " );
while(1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
if (inet_ntop(AF_INET, &cli_addr.sin_addr, str, INET_ADDRSTRLEN) == NULL) {
fprintf(stderr, "Could not convert byte to address\n");
exit(1);
}
fprintf(stdout, "Connected!\nThe client address is :%s\n", str);
//fork new process
int pid = fork();
if (pid == -1 ) {
error("ERROR in new process creation");
close(newsockfd);
continue;
}else if( pid != 0){
//parent process
close(newsockfd);//h edw h prin to continue
printf( " I am parent process %d\n " ,getpid()); //BGALE
if (wait(&status)== -1) /* Wait for child*/
{
perror( " wait " );
}
check_child_exit(status);
continue;
}else if (pid == 0) {
//child process
close(sockfd);
bzero(buffer, 256);
while(1) {
n = read(newsockfd, buffer, 255); //apo socket ston buffer
if (n < 0 )
error("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message", 18);
bzero(buffer, 256);
close(1); //close stdin
dup2( newsockfd, 1);
close(0); //close stdout
dup2( newsockfd, 0);
parse(vector_args,buffer);
execvp(vector_args[0] , vector_args );
perror( " execvp " );
exit(EXIT_FAILURE);
bzero(buffer, 256);
}
close(newsockfd);
break;
}
}
}
Do you have any ideas how could I change my code in order to work properly?
The loop
while (1) {
....
execvp(....);
}
is effectively executed once. The reason is that the successful execvp replaces the code with whatever vector_args requests, and the executed process just exits when done.
If I understand your goals correctly (one process per connection, executing external commands in the loop), you need one more fork, along the lines of
while (1) {
....
if ((pid = fork()) == 0) {
execvp(....);
} else if (pid > 0) {
waitpid(....);
} else {
handle_error();
}
}
If client send pwd, server may recv p w d or pw d or pwd and so on.
In my opinion, if client want to send pwd, client should send pwd\n, server will read command until \n. If server want to send 123, server should send 123\0, client will read until \0. I write a tiny example, you could learn from it. The server code will continue until client quit.
server.c
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void parse(char** argv, char* buffer) {
int i = 0;
argv[i] = strtok(buffer, " ");
while (argv[i] != NULL) argv[++i] = strtok(NULL, " ");
}
void handle_client(int con_socket) {
for (;;) {
char buf[1024];
ssize_t i = 0;
for (;;) {
ssize_t ret = read(con_socket, buf + i, 1);
if (ret == 0) return;
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
++i;
}
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(con_socket);
dup2(pipe_fd[1], 1);
close(pipe_fd[0]);
close(pipe_fd[1]);
char* argv[25];
parse(argv, buf);
execvp(argv[0], argv);
exit(EXIT_FAILURE);
} else {
close(pipe_fd[1]);
for (;;) {
ssize_t ret = read(pipe_fd[0], buf, sizeof(buf));
if (ret == 0) {
write(con_socket, "", 1);
break;
}
write(con_socket, buf, ret);
}
wait(NULL);
}
}
}
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int opt = 1;
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bind(listen_socket, (struct sockaddr*)(&server_addr),
(socklen_t)(sizeof server_addr));
listen(listen_socket, 5);
for (;;) {
int con_socket = accept(listen_socket, NULL, NULL);
if (fork() > 0) {
close(con_socket);
wait(NULL);
continue;
} else {
close(listen_socket);
handle_client(con_socket);
close(con_socket);
break;
}
}
return 0;
}
client.c
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
for (;;) {
printf(">> ");
char buffer[256];
fgets(buffer, 256, stdin);
if (strlen(buffer) == 0) continue;
write(sockfd, buffer, strlen(buffer));
for (;;) {
ssize_t ret = recv(sockfd, buffer, 256, 0);
buffer[ret] = '\0';
printf("%s", buffer);
if (buffer[ret - 1] == '\0') break;
}
}
return 0;
}

The result does not come from the correct branch

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

Sending to client from server [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to send data from a server to a client whenever the client executes a recv() command. As the code stands right now, I cannot get the client to print any data it receives. I cannot figure out whether something is wrong with my server or client, so any help would be appreciated. Thanks!
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stderr, "usage: %s <server-ip> <port>",argv[0]);
return EXIT_FAILURE;
}
char buf[BUF_SIZE];
int status, sock, sock2;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *servinfo; //will point to the results
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_STREAM; //TCP stream sockets
hints.ai_flags = AI_PASSIVE; //fill in my IP for me
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s \n", gai_strerror(status));
return EXIT_FAILURE;
}
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
if ((sock2 = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock2, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
while (1) {
//char msg[BUF_SIZE] = "ashudfshuhafhu";
//char msg[BUF_SIZE];
//fgets(msg, BUF_SIZE, stdin);
//int i = 2;
//if (strlen(msg) == i)
// break;
int bytes_received;
// fprintf(stdout, "Sending %s", msg);
//send(sock, msg , strlen(msg), 0);
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
}
freeaddrinfo(servinfo);
close(sock);
return EXIT_SUCCESS;
}
Server.c
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int close_socket(int sock)
{
if (close(sock))
{
fprintf(stderr, "Failed closing socket.\n");
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
int sock, client_sock;
ssize_t readret;
socklen_t cli_size;
struct timeval tv;
struct sockaddr_in addr, cli_addr;
char buf[BUF_SIZE] = "wetwetwetwetwetwetwetwet";
fd_set readfds, writefds;
fd_set activereadfds, activewritefds;
cli_size = sizeof(&cli_addr);
tv.tv_sec = 5;
tv.tv_usec = 0;
fprintf(stdout, "----- Echo Server -----\n");
/* all networked programs must create a socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Failed creating socket.\n");
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
/* servers bind sockets to ports---notify the OS they accept connections */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
{
close_socket(sock);
fprintf(stderr, "Failed binding socket.\n");
return EXIT_FAILURE;
}
if (listen(sock, 5))
{
close_socket(sock);
fprintf(stderr, "Error listening on socket.\n");
return EXIT_FAILURE;
}
FD_ZERO(&readfds);
FD_SET(sock, &activereadfds);
while (1)
{
fprintf(stdout,"in here.\n");
readfds = activereadfds;
writefds = activewritefds;
FD_ZERO(&activereadfds);
FD_ZERO(&activewritefds);
if (select(51, &readfds, &writefds, NULL, &tv) < 0)
{
perror("select");
return EXIT_FAILURE;
}
for (int i = 0; i < 10; ++i)
{
if (FD_ISSET (i, &readfds))
{
if (i == sock)
{
fprintf(stdout, "main loop. \n");
client_sock = accept(sock,
(struct sockaddr *) &cli_addr, &cli_size);
FD_SET(client_sock, &activereadfds);
FD_SET(client_sock, &activewritefds);
if (client_sock < 0)
{
perror("accept");
return EXIT_FAILURE;
}
} else {
fprintf(stdout, "second loop \n");
readret = send(i,buf, strlen(buf),0);
if (readret < 0)
fprintf(stdout, "yay");
}
}
if (FD_ISSET(i, &writefds))
{ fprintf(stdout, "ugh \n");
readret = send(i,buf,BUF_SIZE,0);
//if (readret > 0)
//while((readret = recv(i, buf, BUF_SIZE, 0)) >= 1)
// {
//if (send(i, buf, readret, 0) != readret)
//{
// close_socket(i);
// close_socket(sock);
// fprintf(stderr, "Error sending to client.\n");
// return EXIT_FAILURE;
//}
}
}
}
close_socket(sock);
return EXIT_SUCCESS;
}
Your server is sending only when the socket is ready for reading, and as the client is never sending, the server isn't either. The server send should happen when the client socket turns up in the writefds, although actually this isn't the correct way to use that feature. Really you should just send, and only add into and worry about writefds if send() caused EAGAIN/EWOULDBLOCK.
You could be getting an undetected error in the client:
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
This should continue:
else if (bytes_received == 0)
{
fprintf(stdout, "peer disconnected\n");
break;
}
else // < 0: error
{
fprintf(stdout, "recv() error %s\n", strerror(errno));
break;
}
You need to print the actual error like this whenever you get an error from a system call.

Second recv call doesn't receive data, halts the execution in C

This is my client program that requests files from the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
void setstring(char *str){
str[MAX_LINE-1]='\0';
}
int main(int argc, char * argv[]){
FILE *fp;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char filename[MAX_LINE],buf[MAX_LINE],reply[MAX_LINE],rec_line[MAX_LINE];
int s;
char msg[MAX_LINE];
int len,new_len,rec_file;
if (argc==2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
else
printf("Client's remote host: %s\n", argv[1]);
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
else
printf("Client created socket.\n");
int send_file_name,rec_msg;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
else{
printf("Client connected.\n");
/* main loop: get and send lines of text */
printf("Hello from server\n");
while(!(strcmp(reply,"bye")==0)){
printf("Enter the file name:\n");
scanf("%s",filename);
setstring(filename);
send_file_name=send(s,filename,strlen(filename)+1,0);
if(send_file_name<0)
fputs("Error sending filename",stdout);
rec_msg=recv(s,msg,sizeof(msg),0);
if(strcmp(msg,"File not found")==0)
printf("File not found\n");
else{
printf("%s\n",msg);
fp=fopen(filename,"w");
printf("CP1\n");
if(rec_file=recv(s,rec_line,sizeof(rec_line),0)>0){
printf("CP2");
printf("String recieved:%s\n",rec_line);
if(len=fwrite(rec_line,1,rec_file+1,fp)>0)
printf("Recieved file\n");
else
printf("Error writing to file\n");
}
else
printf("Not recieved\n");
}
printf("Enter 'bye' to terminate requesting files\n");
scanf("%s",reply);
}
}
return 0;
}
This is my server program that accepts request for files from the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 256
void setstring(char* str){
str[MAX_LINE-1]='\0';
}
int main(){
FILE *fp;
struct sockaddr_in sin;
char buf[MAX_LINE],msg[MAX_LINE],*rec_line;
int len;
int s, new_s,count;
char str[INET_ADDRSTRLEN];
int error_file,send_msg,read_line,send_file;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("0.0.0.0");
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
inet_ntop(AF_INET, &(sin.sin_addr), str, INET_ADDRSTRLEN);
printf("Server is using address %s and port %d.\n", str, SERVER_PORT);
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
else
printf("Server bind done.\n");
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1) {
if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
printf("Server Listening.\n");
printf("Greetings\n");
int rec_file_name=recv(new_s,buf,sizeof(buf),0);
if(rec_file_name>0)
printf("File requested:%s\n",buf);
fp=fopen(buf,"r");
if(fp==NULL)
{
fputs("File not found\n",stdout);
strcpy(buf,"File not found");
if(error_file=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("Successfully send error message to client\n",stdout);
}
else{
bzero(buf,MAX_LINE);
printf("File found :) \n");
strcpy(buf,"OK");
if(send_msg=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("File found message sent to client\n",stdout);
fseek(fp,0,SEEK_END);
int file_size=ftell(fp);
fseek(fp,0,SEEK_SET);
printf("File size:%d\n",file_size);
rec_line=(char *)malloc(sizeof(char)*(file_size));
read_line=fread(rec_line,1,file_size+1,fp);
printf("File read: %s\n",rec_line);
if(send_file=send(new_s,rec_line,strlen(rec_line)+1,0)>0)
printf("File string sent to client\n");
}
}
close(new_s);
}
The problem is that in the client, my second recv() call, where it is supposed to receive the contents of a file, shows nothing. The programs halts at that point, but the server programs displays that it has sent the file contents. The client doesn't receive it.
The basic problem is that you're not checking the return values to see how much data you actually sent and received. So when the client calls:
rec_msg=recv(s,msg,sizeof(msg),0);
it will receive up to sizeof(msg) (512) bytes, which is probably both the OK message the server is sending AND the file contents (after the NUL). Which means when it does a second recv call to get the contents, it blocks, because it already read the contents in the first call and there's no more data waiting in the receive buffer.
Your error-checking is haphazard, and consequently you're certainly missing a problem that occurs before the behavior you're observing. I recommend you follow RW Steven's idiom:
int n;
if( (n = recv(new_s, buf, sizeof(buf), 0)) < 0 ) {
err(EXIT_FAILURE, "recv %d", __LINE__);
}
Test every function call, and handle every error. For simple programs, just call err(3) on error. Do that consistently, and the program's behavior will be much less mysterious (if still occasionally surprising). And don't be afraid of the spacebar! It's easy to hit, and easier still to read.
My other bit of advice, if I may, concerns
int send_file_name,rec_msg;
Names like that are confusing. A name is almost never an integer. For I/O sizes, just use one simple name like n, len, or size. Even if you don't care for yourself, you want to care before publishing your question in an open forum. Otherwise, when people see
send_file_name=send(s,filename,strlen(filename)+1,0);
they may think send is some function other than send(2), or that the person asking the question was careless.
The main problem I see is that neither the client nor the server are handling socket I/O correctly in general. They are not handling the cases where reads and writes transfer fewer bytes then requested, you need to loop the I/O. And the client is reading too many bytes from the server anyway, which is why your second recv() is blocking. And you are relying on a disconnect to indicate the end of the file has been reached, but that does not allow the client to do adequate error checking to know if the full file was actually received or not.
Also, when sending the content of a file, the server is attempting to read the entire file into memory (bad!), not doing adequate error checking on the file I/O, and it is treating the file content as text instead of as binary (don't use strlen() on binary data!).
Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
int sendstring(int sock, const char *str) {
if (!str) str = "";
int len = strlen(str) + 1;
do {
int ret = send(sock, str, len, 0);
if (ret <= 0) return -1;
str += ret;
len -= ret;
}
while (len > 0);
return 0;
}
int readbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (buflen > 0) {
int len = recv(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int readfile(int sock, int fd) {
int filesize;
char buf[MAX_LINE];
if (readbuf(sock, &filesize, sizeof(filesize)) < 0) return -1;
filesize = ntohl(filesize);
while (filesize > 0) {
int len = readbuf(sock, buf, min(sizeof(buf), filesize));
if (len < 0) return -1;
if (fwrite(buf, len, 1, fp) != 1) return -2;
filesize -= len;
}
return 0;
}
int main(int argc, char * argv[]) {
char filename[MAX_LINE], reply[MAX_LINE];
if (argc != 2) {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
char *host = argv[1];
/* translate host name into peer's IP address */
struct hostent *hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET) {
fprintf(stderr, "simplex-talk: unsupported address type %d for host: %s\n", hp->h_addrtype, host);
exit(1);
}
/* build address data structure */
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
printf("Host's remote IP: %s\n", inet_ntoa(&sin.sin_addr));
/* active open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Client created socket.\n");
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
printf("Client connected.\n");
/* main loop: get and send lines of text */
do {
printf("Enter the file name ('bye' to quit):\n");
if (scanf("%512s", filename) != 1) {
printf("Error reading filename\n");
break;
}
if (strcmp(filename, "bye") == 0) {
sendstring(s, "bye");
break;
}
if (sendstring(s, filename) < 0) {
printf("Error sending filename\n");
break;
}
if (readstring(s, reply, sizeof(reply)) < 0) {
printf("Error reading reply\n");
break;
}
if (strcmp(reply, "OK") != 0) {
printf("%s\n", reply);
if (strcmp(reply, "bye") == 0) break;
continue;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
printf("Error opening file\n");
break;
}
printf("Receiving file\n");
int ret = readfile(s, fd);
fclose(fp);
if (ret < 0) {
if (ret == -2)
printf("Error writing file\n");
else
printf("Error reading file\n");
break;
}
printf("Received file\n");
}
while (1);
close(s);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 512
int sendbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (len > 0) {
int len = send(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int sendstring(int sock, const char *str) {
if (!str) str = "";
return sendbuf(sock, str, strlen(str) + 1);
}
int sendfile(int sock, int fd) {
char buf[MAX_LINE];
struct stat s;
if (fstat(fd, &s) < 0) return -2;
int pos = ftell(fp);
if (pos == -1) return -2;
int file_size = s.st_size - pos;
int tmp_file_size = htonl(file_size);
if (sendbuf(sock, &tmp_file_size, sizeof(tmp_file_size)) < 0) return -1;
while (file_size > 0) {
int len = fread(buf, 1, min(sizeof(buf), file_size), fp);
if (len < 1) return -2;
if (sendbuf(sock, buf, len) < 0) return -1;
file_size -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int main() {
char msg[MAX_LINE];
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Server is using address %s and port %d.\n", inet_ntoa(&(sin.sin_addr)), SERVER_PORT);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("simplex-talk: bind");
close(s);
exit(1);
}
printf("Server bind done.\n");
if (listen(s, MAX_PENDING) < 0) {
perror("simplex-talk: listen");
close(s);
exit(1);
}
printf("Server Listening.\n");
/* wait for connection, then receive and print text */
do {
int len = sizeof(sin);
int cli_s = accept(s, (struct sockaddr *)&sin, &len);
if (cli_s < 0) {
perror("simplex-talk: accept");
close(s);
exit(1);
}
printf("Client connected\n");
do {
if (readstring(cli_s, msg, sizeof(msg)) < 0) {
printf("Error reading request\n");
break;
}
if (strcmp(msg, "bye") == 0) break;
printf("File requested: %s\n", msg);
FILE *fp = fopen(msg, "rb");
if (!fp)
{
printf("Cannot open file\n");
if (sendstring(cli_s, "Cannot open file") < 0) {
printf("Error sending reply\n");
break;
}
continue;
}
printf("File found :) \n");
if (sendstring(cli_s, "OK") < 0) {
printf("Error sending reply\n");
fclose(fp);
break;
}
ret = sendfile(cli_s, fp);
fclose(fp);
if (ret < 0) {
printf("Error sending file\n");
break;
}
printf("File sent to client\n");
}
while (1);
close(cli_s);
}
while (1);
close(s);
return 0;
}

Resources