Send file size and then the file itself - c

client-side code:
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
void error(char * msg){
perror(msg);
exit(0);
}
// Returns an string array from function
char *buff(const char *path){
int end = 0;
unsigned char * buf;
int f_write = open(path,O_RDONLY);
end = lseek(f_write,0,SEEK_END);
lseek(f_write,0,SEEK_SET);
buf =(char*)malloc(sizeof(char*)*(end+1));
read(f_write,buf,end);
close(f_write);
buf[end+1]= '\0';
return buf;
}
//connects to the socket
int connection(int portno,struct hostent * server,int sockfd){
struct sockaddr_in serv_addr;
int conn =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);
conn = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
return conn;
}
int main(int argc, char *argv[]) {
int sockfd = -1;
int check =0;
char projname[100]= "project1";
int portno = -1;
int conn = -1;
int file_size =0;
ssize_t len;
int n = -1;
struct hostent *server;
char buffer[256];
int fd =0;
if(argc < 3){
fprintf(stderr,"usage %s hostname port\n",argv[0]);
exit(0);
}
// getting the portnumber
portno = atoi(argv[2]);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
error("Error opening socket");
}
// getting the hostname
server = gethostbyname(argv[1]);
if(server == NULL){
fprintf(stderr,"Error no such host\n");
exit(0);
}
conn = connection(portno,server,sockfd);
if(conn < 0){
printf("%s\n",strerror(errno));
}
int path = open("text.txt",O_CREAT | O_WRONLY, 0644);
if(path < 0){
printf("%s\n",strerror(errno));
}
int remain_data = file_size;
printf("Printing out the file size ");
printf("%d\n",file_size);
char *buffer1 = (char*)malloc(sizeof(char)*file_size+1);
len = recv(sockfd,buffer1,BUFSIZ,0);
printf("%d",len);
buffer1[file_size]= '\0';
printf("printing the sentence\n");
printf("%s\n",buffer1);
int total_read_bytes =0;
int nread =0;
return 0;
}
server-side code
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/socket.h>
void error(char * msg){
perror(msg);
exit(1);
}
int main(int argc, char const *argv[]){
int sockfd =-1;
int newsockfd = -1;
int portno = -1;
int clilen = -1;
int remain_data =0;
char buffer[300];
char buffer1[300];
int peer_socket = -1;
struct sockaddr_in serv_addr,cli_addr;
int n = -1;
struct stat file_stat;
char file_size[256];
ssize_t len;
int sent_bytes =0;
int path = open("project1/text.txt",O_RDONLY);
read(path,buffer1,30);
buffer1[31]= '\0';
printf("%s\n",buffer1);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd <0){
error("Error opening socket");
}
bzero((char*) &serv_addr,sizeof(serv_addr));
portno=atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
error("Error on Binding");
}
listen(sockfd,5);
int fd = open("project1/text.txt",O_RDONLY);
fstat(fd,&file_stat);
clilen = sizeof(cli_addr);
peer_socket = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);
sprintf(file_size,"%d",file_stat.st_size);
//sends file size
len = send(peer_socket,file_size,sizeof(file_size),0);
if(peer_socket <0){
error("Error on accept");
}
off_t offset = 0;
remain_data = file_stat.st_size;
//send the file
while(((sent_bytes=sendfile(peer_socket,fd,&offset,remain_data))>0) &&( remain_data>0)){
fprintf(stdout,"1.Server sent %d bytes from files data, offset is now : %d and remaining data = %d\n",sent_bytes, offset,remain_data);
remain_data -=sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from files data, offest is not: %d and remaing data = %d\n",sent_bytes, offset,remain_data);
}
return 0;
}
I am able to get the size of my file from server side but I am unable to get file content from my server on client side. My client prints out an empty space where the data of the file is supposed to be, I don't know if I am using the recv function correctly the file correctly.
P.S I understand that I must close the sockets when finished.

For safety and robustness, you must check the return values of all the standard library functions you call to check for errors. For recv() and read(), however, you must check and appropriately handle return values for correctness. These functions do not guarantee to transfer the full number of bytes requested, and for network connections it is reasonably common that they don't. If you want to fully transfer a specific number of bytes then you must be prepared to use multiple recv() or read() calls to do so, generally by calling the function in a loop.
You do not check the return value of your recv() call, so if you have a short read -- or if there is an error or if the remote side closes the connection without sending anything -- then your client will not notice, and will simply output whatever garbage happens to be in the buffer.

Related

C Socket TCP, send array to server and response back to client in loop

I'm very new to socket and TCP, I'm trying to send an array of Int to the server, do some sorting and calculating, then send back the result to the client and repeat.
I tried a few different ways, I either got the result after I close the client or got into a infinite loop.
What is the proper way to keep reading from the client until the client hit EOF?
Here is my server code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server, client;
int sock, csock, readSize, addressSize;
char buf[256];
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
bind(sock, (struct sockaddr*)&server, sizeof(server));
listen(sock, 5);
addressSize = sizeof(client);
csock = accept(sock, (struct sockaddr *)&client, &addressSize);
int values[5];
while (read(csock, values, sizeof(values))) {
// Some sorting and calculating here
for (int i = 0; i < 5; i++) {
printf("%d ", values[i]);
}
}
close(sock);
return 0;
}
And here is my client code.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server;
char buf[256];
int sock;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
connect(sock, (struct sockaddr *)&server, sizeof(server));
while (1) {
int values[5] = {0};
for (int i = 0; i < 5; i++)
scanf("%d", &values[i]);
write(sock, values, sizeof(values));
}
return 0;
}
Thanks for your help!
On Linux, I observed that if client is terminated with Ctrl-C, then server exits when read() returns 0 to signify EOF. If client is given a Ctrl-D, the stream's error state is set and this and all future scanf calls fail without setting values. This means values retain their zero initialization, which is sent to server in each iteration of the infinite loop.
Per #user207421, recv() which I guess how read() is implemented may return on error on windows to signify and errors. In this case, server would loop with the original code.
In either case, I added error checking for most of calsl (you should also add it for inet_addr()), and the server will terminate if read() returns either -1 or 0:
server:
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server, client;
int sock, csock;
socklen_t addressSize;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1) {
printf("socket: %s\n", strerror(errno));
return 1;
}
if(bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
printf("bind: %s\n", strerror(errno));
return 1;
}
if(listen(sock, 5) == -1) {
printf("listen: %s\n", strerror(errno));
return 1;
}
addressSize = sizeof(client);
csock = accept(sock, (struct sockaddr *)&client, &addressSize);
if(csock == -1) {
printf("listen: %s\n", strerror(errno));
return 1;
}
int values[5];
ssize_t n;
while ((n = read(csock, values, sizeof(values)))) {
printf("read %zd\n", n);
if(n <= 0) break;
for (int i = 0; i < n / sizeof(*values); i++) {
printf("%d ", values[i]);
}
printf("\n");
}
close(sock);
return 0;
}
and client:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server;
char buf[256];
int sock;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1) {
printf("socket: %s\n", strerror(errno));
return 1;
}
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) == -1) {
printf("connect: %s\n", strerror(errno));
return 1;
}
while (1) {
int values[5] = {0};
for (int i = 0; i < 5; i++) {
int r = scanf("%d", &values[i]);
if(r == EOF) {
return 0;
}
}
ssize_t n = write(sock, values, sizeof(values));
if(n == -1) {
printf("write: %s\n", strerror(errno));
return 1;
}
printf("wrote %zd\n", n);
}
return 0;
}
and here is the output from the server:
$ ./server
read 20 bytes
1 2 3 4 5
and the client (note; client doesn't send partial data):
$ ./client
1
2
3
4
5
wrote 20
1

TCP write() prints char* to itself rather than to buffer only on first socket connection, but works OK on second connection onwards

On the first connection to the Server socket by a Client, the Server prints the output to itself, and leaves the Client blocked. But the second Client onwards receives the output from the Server.
The buffer that is expected to output to the Client is the server uptime.
Why does this happen, is there a way to immediately send the output to the Client and not block it?
To replicate, run 'ruptimeServer' on one terminal, and run 'ruptimeClient [localIPAddress] [serverIPAddress]'.
Below is an example of the I/O to the Server.
[user#linux-3 Lab2]$ ./ruptimeServer
Awaiting connection.
20:42:05 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06 <-- buffer
Write Success
Awaiting connection.
Write Success
Awaiting connection.
Write Success
Awaiting connection.
^CCaught Ctrl+C, closing all connections.
Below is the I/O to the Client.
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
^C
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
10.24.87.66: 20:42:14 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
10.24.87.66: 20:42:18 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06
Below is the code for Server.
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/select.h>
char* get_uptime();
void sig_handl(int sig_num);
int sersock, consock;
int main(int argc, char* argv[]){
struct sockaddr_in serveraddr, clientaddr;
struct sigaction sigIntHandler;
int on = 1;
sigIntHandler.sa_handler = sig_handl;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
char input_buffer[1024] = {0};
int len = sizeof(clientaddr);
char* IP_ADDRESS = "192.168.254.11";
if((sersock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("socket() error");
exit(1);
}
serveraddr.sin_family = PF_INET;
serveraddr.sin_port = htons(28189);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sersock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
perror("bind() error");
exit(1);
}
if(listen(sersock, 10) < 0){
perror("listen() error");
exit(1);
}
char *output;
output = malloc(sizeof(char) * 1024);
signal(SIGINT, sig_handl);
while(1){
printf("Awaiting connection.\n");
if(consock = accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0){
perror("accept() error");
exit(1);
}
output = get_uptime();
if(write(consock, output, 1024) < 0){
perror("write() error");
exit(1);
}
printf("Write Success\n");
close(consock);
}
close(sersock);
}
char * get_uptime(){ //returns uptime on server
char *buffer;
buffer = malloc(sizeof(char) * 1024);
FILE* file = popen("uptime", "r");
fgets(buffer, 100, file);
pclose(file);
return buffer;
}
void sig_handl(int sig_num){
printf("Caught Ctrl+C, closing all connections.\n");
close(consock);
close(sersock);
exit(0);
}
Below is the code for Client.
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
int main(int argc, char* argv[]){
if(argc != 3){
printf("Not enough arguments. To run, \"./ruptimeClient <localhost_IP> <server_IP>\"\n");
return 0;
}
struct sockaddr_in remoteaddr;
char input_buffer[100];
//input_buffer = malloc(sizeof(char) * 100);
int clisock;
char* SERVER_IP = argv[2];
if((clisock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("socket() error");
exit(1);
}
remoteaddr.sin_family = PF_INET;
remoteaddr.sin_port = htons(28189);
remoteaddr.sin_addr.s_addr = inet_addr(SERVER_IP);
if(connect(clisock, (struct sockaddr *)&remoteaddr, sizeof(remoteaddr)) < 0){
perror("Connection failed");
exit(1);
}
printf("Connection Success.\n");
if(read(clisock, input_buffer, 100) < 0){
perror("read() error");
exit(1);
}
//input_buffer = "test";
printf("%s: %s", SERVER_IP, input_buffer);
close(clisock);
return 0;
}
The problem is here:
if(consock = accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0){
That's parsed as if you wrote this:
if(consock = (accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0)){
As a result, consock ends up getting set to 0, which when interpreted as a file descriptor, means standard input. This then gets closed after the first client (the one that hangs), so it's available for subsequent clients, which then get reassigned that now-free FD number. To fix it, add explicit parentheses, like this:
if((consock = accept(sersock, (struct sockaddr *)&clientaddr, &len)) < 0){
the following proposed code:
is for the server
cleanly compiles
does not leak memory
incorporates the comments to the OPs question
and now, the proposed code for the server:
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/select.h>
#include <unistd.h>
#include <string.h>
char* get_uptime( char *buffer, int size );
void sig_handl(int sig_num);
int sersock, consock;
int main( void )
{
struct sockaddr_in serveraddr, clientaddr;
struct sigaction sigIntHandler;
//int on = 1;
sigIntHandler.sa_handler = sig_handl;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
//char input_buffer[1024] = {0};
socklen_t len = sizeof(clientaddr);
//char* IP_ADDRESS = "192.168.254.11";
if((sersock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket() error");
exit(1);
}
serveraddr.sin_family = PF_INET;
serveraddr.sin_port = htons(28189);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sersock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind() error");
exit(1);
}
if(listen(sersock, 10) < 0)
{
perror("listen() error");
exit(1);
}
char *output;
int size = 1024;
char buffer[ size ];
signal(SIGINT, sig_handl);
while(1)
{
printf("Awaiting connection.\n");
if( (consock = accept(sersock, (struct sockaddr *)&clientaddr, &len)) < 0)
{
perror("accept() error");
exit(1);
}
output = get_uptime( buffer, size );
if( write( consock, output, strlen( output ) ) < 0 )
{
perror("write() error");
exit(1);
}
printf("Write Success\n");
close(consock);
}
close(sersock);
}
char * get_uptime( char *buffer, int size )
{ //returns uptime on server
FILE* file = popen("uptime", "r");
fgets( buffer, size, file );
pclose(file);
return buffer;
}
void sig_handl(int sig_num)
{
(void)sig_num;
printf("Caught Ctrl+C, closing all connections.\n");
close(consock);
close(sersock);
exit(0);
}

Using printf with threads and socket programming

I was making a server using socket programming that echoes what the client says to him. But when I print out the message(send by client) and it's length, the message and it's length don't match. I am using printf to print.
What I basically want is to close the connection when the client types "exit". But strcmp("exit",clientmessage) is not working.
server code:
//for running type ./a.out anyportnumber
#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 <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n] = '\0';
printf("%s %d\n",rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
client side input:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~$ telnet localhost 8009
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hhh
jhiklmnop
Server side output:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~/Study/chat$ ./a.out 8009
hhh
5
jhiklmnop
11
Edited code:
//for running type ./a.out anyportnumber
#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 <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
char d[] = {'e','x','i','t','\0'};
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n-2] = '\0';
if(strcmp(d,rmsg) == 0) {
write(s1,"bye",3);
close(s1);
}
rmsg[n-2] = '\n';
rmsg[n-1] = '\0';
write(s1,rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
TCP is a stream-oriented protocol, there are no message boundaries. So you cannot write application logic that depends on the return value of read() as you are doing.
Workarounds for this are length-prefixed strings, or sending the NUL terminator through the socket. You can dream up other mechanisms too, but the client must, within the data stream, tell the server where the message ends; the TCP layer won't do that.
Besides the characters the user is typing in, you're also getting a carriage return (0xd) and linefeed (0xa) character when the user presses the Enter key. That's why you're getting a number 2 larger than you might expect.

variable length message over tcp

I am trying to send variable length message in TCP but the message length that
is printed is always 0. I am using beej guide code for send and receive and pack and unpack to send the header length.Can someone please point out the mistake.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
void packi32(unsigned char *buf, unsigned long i)//from beej guide
{
*buf++ = i>>24; *buf++ = i>>16;
*buf++ = i>>8; *buf++ = i;
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len){
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
int sendus(int s,char *msg)
{
char buf[4];//here 4 is header length
int len = strlen(msg);
packi32(buf,len);
int ll = 4;// ll is header length containing message length
int x;
if((x = sendall(s,buf,&ll))< 0)
printf("value of sent x %d\n",x);
int y = sendall(s,msg,&len);
return y;
}
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;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
char msg[1024] = "hello";
int xx = sendus(sockfd,(char*)msg);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/** unpacki32() -- unpack a 32-bit int from a char buffer (like ntohl())
*/
unsigned long unpacki32(unsigned char *buf)
{
return (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout){
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len){
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN){
time(&current_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int recvme(int s, char *buf)
{
char len[4];
int l = 4;
int n = recvall(s,len,&l,10);
int msg_len = unpacki32(len);
printf("msg_length :%d",msg_len);
int z ;
z = recvall(s,buf,&msg_len,10);
return z;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
if (argc < 3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
n = recvme(sockfd, buffer);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
The basic cause for the failure is in the server's line
int xx = sendus(sockfd,(char*)msg);
- sockfd is the listen() socket, but we have to use the newsockfd returned from accept(), i. e.
sendus(newsockfd, msg);

simple client server in c

i am not able to understand why the code is not working. sendall and revcall are taken from beej guide. Their is no output when i send the data from server to client. Can someone please explain the error in code. It is mostly from beej guide.One of the problems in broken pipe i.e reading when port is closed but when the port is closed i am not able to understand.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len)
{
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
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;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("sockfd : %d",sockfd);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
char msg[1024] = "hello";
int len = sizeof(msg);
int xx = sendall(sockfd,(char*)msg,&len);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout)
{
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len)
{
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN)
{
time(&current_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
if (argc < 3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");;
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
int m = 1024;
n = recvall(sockfd, buffer,&m,10);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
'int xx = sendall(sockfd,(char*)msg,&len);'
'sockfd' is the server listening socket. You should be calling sendall() with 'newsockfd', as returned by the accept() call.

Resources