bad file descriptor with close() socket (c++) - c++

I'm running out of file descriptors when my program can't connect another host. The close() system call doesn't work, the number of open sockets increases. I can se it with
cat /proc/sys/fs/file-nr
Print from console:
connect: No route to host
close: Bad file descriptor
connect: No route to host
close: Bad file descriptor
..
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
using namespace std;
#define PORT 1238
#define MESSAGE "Yow!!! Are we having fun yet?!?"
#define SERVERHOST "192.168.9.101"
void
write_to_server (int filedes)
{
int nbytes;
nbytes = write (filedes, MESSAGE, strlen (MESSAGE) + 1);
if (nbytes < 0)
{
perror ("write");
}
}
void
init_sockaddr (struct sockaddr_in *name,
const char *hostname,
uint16_t port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL)
{
fprintf (stderr, "Unknown host %s.\n", hostname);
}
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
}
int main()
{
for (;;)
{
sleep(1);
int sock;
struct sockaddr_in servername;
/* Create the socket. */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket (client)");
}
/* Connect to the server. */
init_sockaddr (&servername, SERVERHOST, PORT);
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
sock = -1;
}
/* Send data to the server. */
if (sock > -1)
write_to_server (sock);
if (close (sock) != 0)
perror("close");
}
return 0;
}
Fix:
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
}
else
write_to_server (sock);
if (close (sock) != 0)
perror("close");

It looks like the problem is in the structure of your program. Every time through your infinite loop, you're creating a new socket. I'd suggest moving this out of the loop and re-using it.
If you'd like to just fix the way you're doing it now though, use close inside the "connect" failed if statement you have now. The descriptor is allocated by the 'socket' call and only connected with the 'connect' call. By setting your 'sock' variable to -1, you're throwing away the descriptor allocated by 'socket'. Call close, then set it to -1 and you should be set.

Related

Sending struct UDP socket twice instead of one

I'm new to c++ and need help.
I use an UDP server to receive structure however i have problem to read it , the client send a structure I call : ChannAccessReq so the structure is send and the server receive it with RECVFROM and I use a general structure by reading the header (H1) of the struct only and then i do a read when a condition is fullfill with a more precise structure (temp2) for the buffer. However the client need to send the message twice , the first time it goes until recvfrom and the second it reach read() (i think) I tried all the day and wonder if its the size of the buffer ?
I think the most sensitive part is in the server with the recvfrom() who have a struct different from the read() just after..
I hope it's clear!
here is the server :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct IntMsgHeaderType {
uint8_t code ; // Code message7
uint8_t bourrage ; // Octet de bourrage
uint16_t ParamLength; // Longueur eventuel données complémentaires
} HeaderInt;
typedef struct TextMessage //TESTTESTTEST
{
HeaderInt H; // Code message7
};
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
struct TextMessage * temp = (TextMessage *)malloc(sizeof(struct TextMessage));
HeaderInt *H1 =(HeaderInt *)malloc(104+sizeof(HeaderInt));
ChanAccesReq *temp2=(ChanAccesReq *)malloc(sizeof(ChanAccesReq));
if (!argv[1]) {
fprintf(stderr,"no port number provided");
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
cliAddrLen = sizeof(echoClntAddr);
int nbrOctet;
if (recvfrom(sock, H1, sizeof(*H1), 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)>0 && H1->code==1){
//read(sock,H1,sizeof(*H1));
std::cout<<"taille nbrOctet : "<<nbrOctet<<'\n';
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
read(sock, temp2, sizeof(*temp2));
//read(sock,temp2,sizeof(*temp2))>0;
std::cout<<unsigned(temp2->P.linkAddr)<<'\n';
};
}
close(sock);
return 0;
}
and here the client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct {
char transMode ;
uint8_t linkAddr;
} ChanAccessReqParam;
typedef struct {
HeaderInt H;
ChanAccessReqParam P;
} ChanAccesReq ;
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
int structLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
if (!argv[1]) {
fprintf(stderr,"No server IP sepcified at arg 1\n");
exit(1);
}
else if (!argv[2]) {
fprintf(stderr,"No port Number Sepcified at arg 2\n");
exit(2);
}
ChanAccesReq test { 1 ,1,0,'c',15};
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
echoServPort = atoi(argv[2]); /* Use given port, if any */
/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
int tempint = 0;
tempint = sendto(sock, (ChanAccesInd*)&test, 10+(sizeof(test)), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr));
if (tempint == -1 ) {
printf("Sent struct size: %d\n", tempint);
DieWithError("sendto() sent a different number of bytes than expected\n");
}
close(sock);
exit(0);
}
Thank you for your help
In C++ you have to define the type of the parameters.
As I deduced from the calling place, it should be int and bool.
int GesCanSlotSendTimeInd( int subscIPAddr , bool TransModeFlash){
return 0;
}
Also it is possible to use const qualifier, but you also need the type.
int GesCanSlotSendTimeInd( const int& subscIPAddr , const bool& TransModeFlash){
return 0;
}
For further info please look at cpp reference
You need to use non-blocking mode to poll for recvfrom and sendto at the same time. See here for more details.
int main(int argc, const char** argv) {
setvbuf(stdout, NULL, _IONBF, 0);
int portnum = 9988;
if (argc >= 2) {
portnum = atoi(argv[1]);
}
printf("Listening on port %d\n", portnum);
int sockfd = listen_inet_socket(portnum);
struct sockaddr_in peer_addr;
socklen_t peer_addr_len = sizeof(peer_addr);
int newsockfd = accept(sockfd, (struct sockaddr*)&peer_addr, &peer_addr_len);
if (newsockfd < 0) {
perror_die("ERROR on accept");
}
report_peer_connected(&peer_addr, peer_addr_len);
// Set nonblocking mode on the socket.
int flags = fcntl(newsockfd, F_GETFL, 0);
if (flags == -1) {
perror_die("fcntl F_GETFL");
}
if (fcntl(newsockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror_die("fcntl F_SETFL O_NONBLOCK");
}
while (1) {
uint8_t buf[1024];
printf("Calling recv...\n");
int len = recv(newsockfd, buf, sizeof buf, 0);
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
usleep(200 * 1000);
continue;
}
perror_die("recv");
} else if (len == 0) {
printf("Peer disconnected; I'm done.\n");
break;
}
printf("recv returned %d bytes\n", len);
}
close(newsockfd);
close(sockfd);
return 0;
}
"A couple of notable differences from the blocking version:
The newsockfd socket returned by accept is set to nonblocking mode by calling fcntl.
When examining the return status of recv, we check whether errno is set to a value saying that no data is available for receiving. In this case we just sleep for 200 milliseconds and continue to the next iteration of the loop."
You can still send() and recvfrom() on the same socket since that you dont really need 2 differents process if that's what you need

C++ Sending vector<uchar> with socket loosing data

Im trying to send an Image with sockets from the server to the client, but for some reason im losing a lot of data.
this is my server:
#include <opencv2/imgcodecs.hpp>
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <string>
#define PORT 8080
using namespace cv;
using namespace std;
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
Mat image = cv::imread("Rio.jpg",IMREAD_COLOR); //BGR
std::vector< uchar > buf;
cv::imencode(".jpg",image,buf);
cerr << send(new_socket , buf.data() , buf.size(),0);
cerr << buf.data();
return 0;
}
The output of this file is:
562763����
562763 should be the size of data that is send to the client and ���� should be the data.
This is my Client:
#include <opencv2/imgcodecs.hpp>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <netinet/in.h>
#include <iostream>
#define PORT 8080
using namespace std;
using namespace cv;
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
int l = 0;
std::string data = "";
do{
data += buffer;
l += strlen(buffer);
valread = read( sock , buffer, 1024);
}while(valread != 0);
cerr << l;
char* c = const_cast<char*>(data.c_str());
std::vector<uchar> vec(c,c+l);
Mat image2 = cv::imdecode(vec, 1);
// cv::imwrite("test22.jpg",image2);
return 0;
}
The output i get is:
87567Corrupt JPEG data: 175 extraneous bytes before marker 0xec
87567 should be the size of the data received and because there is data missing the jpeg cant be created
When im sending a message like "This is a test" the full text is received by the client.
You have two major flaws, one which could lead to an infinite loop, and one which leads to the problem you experience:
The infinite loop problem will happen if read fails in the client and it returns -1. -1 != 0, and then read will continue to read -1 forever.
The second and main problem is that you treat the data you send between the programs a strings which it is not. A "string" is a null-terminated (i.e. zero-terminated) sequence of characters, your image is not that. In fact, it might even contain embedded zeros inside the data which will give you invalid data in the middle as well.
To solve both problem I suggest you change the reading loop (and the variables used) to something like this:
uchar buffer[1024];
ssize_t read_result;
std::vector<uchar> data;
// While there's no error (read returns -1) or the connection isn't
// closed (read returns 0), continue to append the received data
// into the vector
while ((read_result = read(sock, buffer, sizeof buffer)) > 0)
{
// No errors, no closed connection
// Append the new data (and only the new data) at the end of the vector
data.insert(end(data), buffer, buffer + read_result);
}
After this loop, and if read_result == 0, then data should contain only the data that was sent. And all of it.
In your client you are using buffer before you have read anything to it. You also are assuming that it is null terminated.
Something like this seems better
std::string data = "";
for (;;)
{
valread = read( sock , buffer, 1024);
if (valread <= 0)
break;
data.append(buffer,valread);
}

Reason for connection error in socket programming (on client side)?

I'm having issues with my connect() method on the client side of my socket programming. I'm not sure if the issue is with my code or my method of running it. I'm running it in two seperate terminal windows - one for the server (which I'm running first) with the command './server 8080' and one for the client with the command './client 4 8080 hello'. When I run my code, the server program stops in the while loop just after the printf("this prints\n") line. I presume this means that it is waiting for a client to connect to it. The client program fails on the connect() call, and prints out my error message "Connection Failed". My code is posted below.
Server Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#define bufsize 1024
void eatZombies(int n){
wait3(NULL,WNOHANG,NULL); // Nom Nom
}
int main(int argc, char *argv[]){
int sock, length, msgsock, status;
struct sockaddr_in server;
pid_t id;
signal(SIGCHLD, &eatZombies);
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(atoi(argv[1])); // this time 1st arg is port#
if(bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Error binding the socket\n");
exit(0);
}
if(listen(server_fd, SOMAXCONN) < 0){
printf("Error listening for connections\n");
exit(0);
}
char buffer[1024] = {0};
char *hello = "Hello from server";
int addrlen = sizeof(server);
while(1){
printf("this prints\n");
int client_fd = accept(server_fd, (struct sockaddr *)&server, (socklen_t*)&addrlen);
printf("this doesnt\n");
if(client_fd < 0){
printf("Error accepting connection\n");
exit(0);
}
// the next call makes a new child process that will actually handle the client.
id = fork();
// when id == 0, this is the child and needs to do the work for the server.
// when if > 0, this is the parent, and it should just loop around,
// when id < 0, we had an error.
if(id > 0){
continue;
}
else if(id < 0){
printf("Error\n");
exit(0);
}
read(client_fd, buffer, 1024);
printf("%s\n", buffer);
write(client_fd, hello, strlen(hello), 0);
printf("Hello message sent\n");
exit(0);
}
return 0;
}
Client Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define bufsize 1024
int main(argc, argv) int argc; char *argv[];{
int sock, rval;
struct hostent *host;
struct sockaddr_in server; // not a pointer
char buf[bufsize];
printf("%d\n", argc);
if(argc != 4){
printf("usage:\ntcpclient hostname port string\n\n");
return(-1);
}
// look up hostname (server) using DNS
if ((host = gethostbyname(argv[1])) == 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
return(-1);
}
// Set up fields for socket to point to host and port
bcopy(host->h_addr, &server.sin_addr, host->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
// Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("Socket Creation Failed\n");
exit(0);
}
// connect (3-way handshake)
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Connection Failed\n");
exit(0);
}
// Copy the arg into buf so we can send it to the server
strncpy(buf, argv[3], bufsize);
// Send sentence to server
send(sock, buf, strlen(buf), 0);
printf("Message sent\n");
// read response from server
rval = read(sock, buf, bufsize);
// print result to window
fprintf(stdout,"%s\n", buf);
close(sock);
}
When running ./client 4 8080 hello, 4 is the host name. You meant to call ./client localhost 8080 hello.
So it was just a mistake in calling the application, not in the code.

Socket Server with Multiple clients. Killing child processes

I have been writing a server that supposed to work with multiple clients using fork().
I am closing the sockets and exiting the child processes, but after handling all the clients I end up with tons of child processes (Have checked it with ps -ef).
Am I missing something here?
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "sbb_socket.h"
#include "bond_container.h"
#include <iostream>
#define SBB_ANY
void do_process(int sd_current);
int main(int argc, char* argv[])
{
/*
* get the number of clients from argument
*/
long client_count = 1;
if (argc > 1 && strtol(argv[1], NULL, 10) > 0) {
client_count = strtol(argv[1], NULL, 10);
}
pid_t pid;
int sd_current;
/*
* get an internet domain socket
*/
int sd;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/*
* set up the socket structure
*/
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
#ifdef SBB_ANY
/* set to INADDR_ANY if want server to be open to any client on any machine */
sock_addr.sin_addr.s_addr = INADDR_ANY;
#else
char hostname[128];
/*
* we'll default to this host and call a section 3 func to get this host
*/
if( gethostname(hostname,sizeof(hostname)) ){
fprintf(stderr," SBB gethostname(...) failed errno: %d\n", errno);
exit(1);
}
//printf("SBB gethostname() local hostname: \"%s\"\n", hostname);
/*
* set up socket structure for our host machine
*/
struct hostent *hp;
if ((hp = gethostbyname(hostname)) == 0) {
fprintf(stderr,"SBB gethostbyname(...) failed errno: %d exiting...\n", errno);
exit(1);
}
sock_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
#endif
sock_addr.sin_port = htons(PORT);
/*
* bind the socket to the port number
*/
if (bind(sd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) == -1) {
perror("bind");
exit(1);
}
/*
* advertise we are available on this socket/port
*/
if (listen(sd, 5) == -1) {
perror("listen");
exit(1);
}
while(1)
{
/*
* wait for a client to connect
*/
struct sockaddr_in sock_addr_from_client;
socklen_t addrlen = sizeof(sock_addr_from_client);
if ((sd_current = accept(sd, (struct sockaddr *) &sock_addr_from_client, &addrlen)) == -1) {
fprintf(stderr,"SBB accept(...) failed errno: %d exiting...\n", errno);
exit(1);
}
/*
* block on socket waiting for client message
*/
if ((pid = fork()) < 0) {
printf("Error on fork");
exit(1);
}
if (pid == 0) {
close(sd);
do_process(sd_current);
exit(0);
}
else {
close(sd_current);
}
}
}
The hanging child processes are probably zombie processes.
You could do for example following for avoiding problem:
Use waitpid() of wait() in parent process to get rid of zombies.
Use 'double fork' trick to put child processes under init process.

Client-server text file transfer using UDP & sockets in C++, server creates a blank file

First of all, I'd like to point out that i'm not a good programmer, so please be patient with me. The logic in the program is as follows: the client sends the server a text file, the server saves it under a different name. In short, very similar to this topic:
" File transfer server/client using socket " except that I'm using a different protocol. I think I've managed to succesfully send the file, but it seems like the server, afters creating a blank file, stucks in a loop/doesn't write anything in it.
Here's the code for the client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 100
#define PLIK "/home/aatami/Documents/programowanie/serwer/plik.txt"
#define LENGTH 512
int main(int argc, char *argv[]) {
int sd, rc, i,fd;
unsigned int cliLen;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
char buf[LENGTH];
/* check command line args */
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
/* get server IP address (no check if input is IP address or DNS name */
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0); /* port 0 - system gets the first free one */
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
/* send data */
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
/* send text file */
char sdbuf[LENGTH];
printf("[Client] Sending %s to the Server... ", PLIK);
FILE *fs = fopen(PLIK, "r");
if(fs == NULL)
{
printf("ERROR: File %s not found.\n", PLIK);
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0)
{
if(send(sd, sdbuf, fs_block_sz, 0) < 0)
{
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", PLIK, errno);
break;
}
bzero(sdbuf, LENGTH);
}
printf("Ok File %s from Client was Sent!\n", PLIK);
}
return 1;
}
And the code for the server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include <errno.h>
#define LENGTH 512
#define LOCAL_SERVER_PORT 1500
#define MAX_MSG 100
#define PLIKSERV "/home/aatami/Documents/programowanie/serwer/plikserv.txt"
int main(int argc, char *argv[]) { /* licznik argumentow, tablica argumentow */
int sd, rc,nsockfd;
unsigned int n,cliLen;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
char buf[512],sbuf[LENGTH];
/* socket creation */
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(LOCAL_SERVER_PORT);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {
printf("%s: cannot bind port number %d \n",
argv[0], LOCAL_SERVER_PORT);
exit(1);
}
printf("%s: waiting for data on port UDP %u\n",
argv[0],LOCAL_SERVER_PORT);
/* server infinite loop */
while(1) {
/* init buffer */
memset(msg,0x0,MAX_MSG);
/* receive message */
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, 0,
(struct sockaddr *) &cliAddr, &cliLen);
if(n<0) {
printf("%s: cannot receive data \n",argv[0]);
continue;
}
/* print received message */
printf("%s: from %s:UDP%u : %s \n",
argv[0],inet_ntoa(cliAddr.sin_addr),
ntohs(cliAddr.sin_port),msg);
unsigned int sin_size = sizeof(struct sockaddr_in);
FILE *fr = fopen(PLIKSERV, "a");
if(fr == NULL)
printf("File %s Cannot be opened file on server.\n", PLIKSERV);
else
{
bzero(sbuf, LENGTH);
int fr_block_sz = 0;
while((fr_block_sz = recvfrom(sd, buf, LENGTH, 0,(struct sockaddr *) &cliAddr, &cliLen)) > 0)
{
int write_sz = fwrite(buf, sizeof(char), fr_block_sz, fr);
if(write_sz < fr_block_sz)
{
perror("File write failed on server.\n");
}
bzero(buf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512)
{
break;
}
}
if(fr_block_sz < 0)
{
if (errno == EAGAIN)
{
printf("recv() timed out.\n");
}
else
{
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
exit(1);
}
}
printf("Ok received from client!\n");
fclose(fr);
}
}/* end of server infinite loop */
return 0;
}
Any help greatly appreciated!
After seen your code I'd suggest try to send a "Hello world\n" from client to the server, see if you get it there. Once you make the connection between client and server then try to expand the code to do a file transfer.
But keep this in mind about UDP:
"UDP uses a simple transmission model with a minimum of protocol mechanism. It has no handshaking dialogues, and thus exposes any unreliability of the underlying network protocol to the user's program. As this is normally IP over unreliable media, there is no guarantee of delivery, ordering or duplicate protection. If error correction facilities are needed at the network interface level, an application may use the Transmission Control Protocol (TCP) which is designed for this purpose."
As you start the client, it sends all packets as fast as possible, could it be that the packets get lost or disordered or even duplicates at the server site. I also suggest waiting for a packet to acknowledge the correct reception. I mean, when then server receives a packet it sends a packet to acknowledge it to the client. This way, a conversation (dialog) could be held and the transfer accomplished satisfactory.