i have been trying to find how to send a file in chunks in C or C++
i looked at some examples in here did not find good example. i am very new to sockect programming in C/C++
http://beej.us/guide/bgnet/html/single/bgnet.html
any ideas how i need to send files in chunk between client and server? client requesting the file, server sending it back.
i found this for send but not sure about receiving it.
#include <sys/types.h>
#include <sys/socket.h>
int sendall(int s, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
I just wrote this code for receiving files in Client using linux sockets in C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 4118
#define MaxBufferLength 1024 // set the size of data you want to recieve from Server
int main()
{
int sockFd, bytesRead= 1, bytesSent;
char buffer[MaxBufferLength];
struct sockaddr_in server, client;
server.sin_port= htons(PORT);
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
sockFd = socket(AF_INET, SOCK_STREAM, 0);
if(sockFd < 0)
printf("Unable to open socket\n");
int connectionSocket = connect(sockFd, (struct sockaddr *) &server, sizeof(struct sockaddr) );
if(connectionSocket < 0)
perror("connection not established\n");
int fd = open("helloworlds.txt",O_CREAT | O_WRONLY,S_IRUSR | S_IWUSR);
if(fd == -1)
perror("couldn't openf iel");
while(bytesRead > 0)
{
bytesRead = recv(sockFd, buffer, MaxBufferLength, 0);
if(bytesRead == 0)
{
break;
}
printf("bytes read %d\n", bytesRead);
printf("receivnig data\n");
bytesSent = write(fd, buffer, bytesRead);
printf("bytes written %d\n", bytesSent);
if(bytesSent < 0)
perror("Failed to send a message");
}
close(fd);
close(sockFd);
return 0;
}
Hope this helps
Take a look at TCP_CORK (man 7 tcp).
But really, except you want to become a socket/network programming expert, use a library !
Just think of your next problem: data encryption (e.g. HTTPS/SSL). Libraries care for the gory details...
Related
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);
}
I have a unix CAN socket created as below:
#include <linux/can.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
int main() {
struct can_frame _msg;
struct sockaddr_can addr;
struct ifreq ifr;
int _sock_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (_sock_fd < 0) {
}
strcpy(ifr.ifr_name, "can0");
if (0 != ioctl(_sock_fd, SIOCGIFINDEX, &ifr)) {
}
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
fcntl(_sock_fd, F_SETFL, O_NONBLOCK);
if (0 != bind(_sock_fd, (struct sockaddr*)&addr, sizeof(addr))) {
}
while (1) {
ssize_t size = 0;
ssize_t tmp = 0;
while (size < sizeof(struct can_frame)) {
tmp = read(_sock_fd, &_msg, sizeof(struct can_frame));
if (tmp <= 0) {
printf("0\n");
}
size += tmp;
}
printf("%x %x %lx\n", _msg.can_id, _msg.can_dlc, *((uint64_t*)_msg.data));
}
return 0;
}
When I do read on this socket, i always get message immediately even if sender does not send anything. read always read duplicate of latest recieved message instead of waiting for next. I perform reading as below:
size_t size = 0;
while (size < sizeof(struct can_frame)) size += read(_sock_fd, &_msg, sizeof(struct can_frame));
It is confusing for me, why read always returns duplicated message intead of waiting for next one. If I call read function in loop with yeld, it spawns millions of duplicates of same message when sender sent just one: candump utility shows received messages right way. Why does it have this behavior?
I have written a C++ demo example. It transfers a file from a server to client.When, I run this program in the local host, it works fine. However, when I run this program over the network the file transfer is incorrect. The image size received is larger than the image size sent. Also, why the same works on the local host? I have tried changing the port number also.
Here is the program -
Server
/** man 2 socket **/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
char msg[] = "Shreyas..first socket prog";
int sock , sock_active;
struct sockaddr_in server, client;
int sent,ret;
unsigned int len;
char buffer[1024];
FILE *fp;
if ( (sock = socket(AF_INET,SOCK_STREAM,0)) == -1 )
//if ( (sock = socket(AF_INET,SOCK_DGRAM ,0)) == -1 )
{
perror("Sock:");
}
server.sin_family = AF_INET;
server.sin_port = htons(15000);
//server.sin_addr.s_addr = INADDR_ANY;
inet_aton("136.170.195.17", &(server.sin_addr));
bzero(&server.sin_zero, 8);
len = sizeof(struct sockaddr_in);
if( ret = (bind( sock, (struct sockaddr *)&server, len)) == -1 )
{
perror("bind :");
}
ret = listen(sock, 0);
while(1)
{
if( (sock_active = accept(sock, (struct sockaddr *)&client, &len)) == -1 )
{
perror("Problem in active socket:");
}
fp = fopen("./Tiger.JPG","rb");
if( fp == NULL )
{
cout<<"Error open file";
return -1;
}
memset(buffer, 1024,0);
int packets = 0;
int count;
//while ( fgets(buffer,1024,fp ) != NULL )
while( ! feof(fp) )
{
packets++;
cout<<"Client IP address is "<<inet_ntoa(client.sin_addr)<<endl;
cout<<"Client Port address is "<<ntohs(client.sin_port)<<endl;
/** Fread is reliable when using to find out the EOF , in feof(fp **/
count = fread(buffer,1,sizeof(buffer),fp);
/** fgets doesn't move the FP correctly */
//fgets(buffer,sizeof(buffer),fp);
cout<<"Read number of bytes ="<<count;
sent = send(sock_active, buffer, sizeof(buffer),0);
cout<<"The number of bytes sent ="<<sent<<"packet number = "<<packets<<endl;
memset(buffer, 1024,0);
}
cout<<"CLose current socket"<<endl;
close(sock_active);
fclose(fp);
}
cout<<"CLosing socket now" <<endl;
close(sock);
return 0;
}
Client socket program -
/** man 2 socket **/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[])
{
struct sockaddr_in server;
int ret;
int sock;
int read_val = 1;
unsigned int len;
if ( (sock = socket(AF_INET,SOCK_STREAM,0)) == -1 )
{
perror("Sock:");
}
if( argc != 2 )
{
cout<<"Pass the Server IP "<<endl;
exit(EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_port = htons(15000);
inet_aton(argv[1], &(server.sin_addr));
bzero(&server.sin_zero, 8);
len = sizeof(server);
if ( (ret = connect(sock, (struct sockaddr *)&server,sizeof(server))) == -1)
{
perror("Connect failed:");
exit(-1);
}
char msg[1024];
memset(msg,0,1024);
FILE *fp_w;
fp_w = fopen("./try.JPG","wb");
while( read_val)
{
read_val = recv(sock,(char *)msg,sizeof(msg),0);
fwrite(msg,1,sizeof(msg),fp_w);
}
cout<<"Read is complete"<<endl;
fclose(fp_w);
close(sock);
return 0;
}
May be you should modify this block of code in your client.
while( read_val)
{
read_val = recv(sock,(char *)msg,sizeof(msg),0);
fwrite(msg,1,sizeof(msg),fp_w);
}
recv function will not always receive the number of bytes you want to receive. You have to use the return value of recv to know the number of bytes actually read and use that count to write to file.
I would write this block as,
while( read_val)
{
read_val = recv(sock,(char *)msg,sizeof(msg),0);
if ( read_val > 0)
{
fwrite(msg,1,read_val,fp_w); // I am using `read_val` while writing.
}
}
While working with file/socket io APIs, its not good to assume that it read/wrote exact number of bytes you asked to.
You are making the usual mistake of assuming that recv(), fread(), etc. fill the buffer. They aren't required to do that. They return a count of the number of bytes that were actually received. You have to use that count as the length argument when sending,
You have to send actual number of bytes read:
count = fread(buffer,1,sizeof(buffer),fp);
cout<<"Read number of bytes ="<<count;
if ( count > 0)
sent = send(sock_active, buffer, count,0);
The same for the client while reading:
while( read_val)
{
read_val = recv(sock,(char *)msg,sizeof(msg),0);
if ( read_val > 0) {
fwrite(msg,1,read_val,fp_w)
} else if ( red_val == -1) {
// an error has occured
break;
} else {
// peer has closed the connection
break;
{
}
this is client server application I want to establish SIP (session initiation protocol) between client and server.
So please anyone guide me how can I do this.
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/tcp.h>
#define MYPORT 3490 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXDATASIZE 100
void str_server(int);
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(void)
{
int sockfd, numbytes,new_fd, optlen; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
struct tcp_info info;
socklen_t sin_size;
struct sigaction sa;
char buf[MAXDATASIZE];
int yes=1;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
while(1) { // main accept() loop
sin_size = sizeof their_addr;
getchar();
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
&sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n", \
inet_ntoa(their_addr.sin_addr));
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if ((numbytes=recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received From Client: %s\n",buf);
str_server(sockfd);
FILE *fp = fopen( "adventure.mpg", "rb" );
//if(!fork())
// execlp("gedit", "gedit", "SIPFILE.txt", NULL);
//system("popen /home/umair/Documents/CurrentData/SIPFILE.txt");
//ShellExecute(GetDesktopWindow(), "open","ls /home/umair/Documents
/CurrentData/SIPFILE.txt",NULL, NULL, SW_SHOW);
if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
void str_server(int sock)
{
char buf[1025];
const char* filename = "test.text";
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("Can't open file for reading");
return;
}
while (!feof(file))
{
int rval = fread(buf, 1, sizeof(buf), file);
if (rval < 1)
{
printf("Can't read from file");
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(sock, &buf[off], rval - off, 0);
if (sent < 1)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes writable
// again before failing the transfer...
printf("Can't write to socket");
fclose(file);
return;
}
off += sent;
}
while (off < rval);
}
fclose(file);
}
//client.c :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#define PORT 3490 // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
void RecvFile(int , const char* );
FILE *filename;
int main(int argc, char *argv[])
{
int sockfd, numbytes, optlen;
char buf[MAXDATASIZE];
char *message;
struct hostent *he;
struct tcp_info info;
struct sockaddr_in their_addr; // connector's address information
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(PORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof their_addr) == -1) {
perror("connect");
exit(1);
}
printf("connect successfull\n");
/* if (send(sockfd, "Hello, world!\n", 14, 0) == -1)
perror("send");
printf("send successfull\n");
*/
message = "GET /?st=1 HTTP/1.1\r\nHost: www.msn.com\r\n\r\n";
if( send(sockfd , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
RecvFile(sockfd , message);
optlen = sizeof(info);
if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received: %s\n",buf);
close(sockfd);
return 0;
}
void RecvFile(int sock, const char* filename)
{
int rval;
char buf[0x1000];
FILE *file = fopen(filename, "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
}
while (!feof(file));
fclose(file);
}
Any Suggestion?
I am not sure what you are trying to do with SIP, but the code snippet you've provided shows only establishing a TCP/IP connection. If you intend to do a SIP server-client application, I suggest that you look for a library to help you along the way.
One that I know of that is very complete is called Sofia SIP:
http://sofia-sip.sourceforge.net/
It's written by Nokia for Linux in C language.
Source code is available here: http://gitorious.org/sofia-sip/sofia-sip/trees/master
(Older http://sourceforge.net/p/sofia-sip/git/ci/master/tree/)
you can learn about sipp scenarios and message passing through this utility and its documentation.
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.