Simple server in c does not work - c

I coded this little server and it doesn't work. The message directly at the beginning isn't printed out as well and I don't know how to analyse the problem by using gdb. Could you help me? Is there any library missing or whats wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 7890
int main(void) {
printf("HelloWorld");
int sockfd, sock_client;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("Could no open socket\n");
}
int yes = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) == -1) {
printf("Coud not reuse\n");
}
printf("socket was created");
struct sockaddr_in sockaddr_host, sockaddr_client;
sockaddr_host.sin_family = AF_INET;
sockaddr_host.sin_port = htons(PORT);
sockaddr_host.sin_addr.s_addr = 0;
memset(&(sockaddr_host.sin_zero), '\0', 8);
if (bind(sockfd, (struct sockaddr *) &sockaddr_host, sizeof (sockaddr_host)) == -1) {
printf("Could not bind socket");
}
if (listen(sockfd, 1) == -1) {
printf("Could not start listening");
} else {
printf("Server is listening on %s: %d", inet_ntoa(sockaddr_host.sin_addr), ntohs(sockaddr_host.sin_port));
}
while (1) {
socklen_t client_length = sizeof (sockaddr_client);
if ((sock_client = accept(sockfd, (struct sockaddr *) &sockaddr_client, &client_length)) == -1) {
printf("Could not accept connection");
}
printf("sever: got connection from %s on port %d", inet_ntoa(sockaddr_client.sin_addr), ntohs(sockaddr_client.sin_port));
char message[] = "Hello\n";
if (send(sockfd, message, sizeof (message), 0) == -1) {
printf("Could not send message");
}
close(sock_client);
close(sockfd);
}
return 0;
}

If you were missing a library, the linker would already complain.
Standard output is usually line buffered. Add a newline after HelloWorld and you will see at least the first output.
printf("HelloWorld\n");
Same with the other printf.
After adding \n to each printf, you will see
HelloWorld
socket was created
Server is listening on 0.0.0.0: 7890
When you now connect to your server, e.g. with netcat
nc localhost 7890
your server will output
sever: got connection from 127.0.0.1 on port 36496
Some errors remain though.
if(send(sockfd, message, sizeof(message), 0) == -1) {
should be rather
if(send(sock_client, message, sizeof(message) - 1, 0) == -1) {
Otherwise the server sends the message to itself. Also sizeof(message) includes the final \0.
Finally, you shouldn't close(sockfd);, if you want to continue receiving further connection requests beyond the first one.

As you said
The message directly at the beginning isn't printed out as well
After the printf add fflush as
printf("HelloWorld");
fflush(stdout);
Is there any library missing
I don't thinks so any library is missing because you have successfully compiled the program and created the executable.

Related

Client code is unable to read data from server [sockets]

My objective is to implement a simple data transfer from server to client. The problem is that the client is unable to read data from the server most of the time (it only works sometimes) even though the server says that the transfer was successful.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
void main() {
int sock = socket(AF_INET, SOCK_STREAM, 0), option = 1;
struct sockaddr_in address;
socklen_t addrlen = sizeof(address);
char buffer[1024] = {0};
char source_file[] = "<path>/something.txt";
char fname[] = "something.txt";
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
if(bind(sock, (struct sockaddr*) &address, sizeof(address)) == -1){
perror("Could not bind to address");
return;
}
if(listen(sock, 5) == -1) {
perror("Error while listening to connections");
return;
}
int new_socket = accept(sock, (struct sockaddr*) &address, &addrlen);
if(new_socket == -1){
perror("Error connecting to client");
exit(EXIT_FAILURE);
}
else printf("Connected to client\n");
// first send the filename
if(send(new_socket, fname, sizeof(fname), 0) == -1){
perror("Error while sending file");
return;
}
printf("Sending file %s\n\n", source_file);
FILE* f = fopen(source_file, "r");
// send the contents of the file
while(fgets(buffer, sizeof(buffer), f)){
printf("Sending %s", buffer);
if(send(new_socket, buffer, strlen(buffer), 0) == -1)
perror("Error while sending\n");
else printf("Successfully sent\n\n");
memset(buffer, 0, sizeof(buffer));
}
printf("File transfer complete\n");
fclose(f);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
void main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
long val;
struct sockaddr_in address;
char buffer[1024] = {0};
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &address.sin_addr) == -1){
perror("Invalid IP value");
exit(EXIT_FAILURE);
}
if(connect(sock,(struct sockaddr*) &address, sizeof(address)) == -1){
perror("Connection Error");
exit(EXIT_FAILURE);
}
else printf("Connected to server\n");
// Get file name from server
if(read(sock, buffer, sizeof(buffer)) == -1){
perror("Could not read filename from server");
exit(EXIT_FAILURE);
}
printf("Receiving file %s\n", buffer);
FILE *f = fopen(buffer, "w");
// printf("%ld", read(sock, buffer, sizeof(buffer)));
while((val = read(sock, buffer, sizeof(buffer)))){
if (val == 0) break;
if (val == -1) {
perror("Error reading the content");
break;
}
printf("Read returned %ld\n", val);
printf("Received %s", buffer);
fputs(buffer, f);
memset(buffer, 0, sizeof(buffer));
}
printf("File transfer complete\n");
fclose(f);
}
Sample text file for data transfer
Hello there!
Nice to meet you.
This is a text file.
Bye Bye :)
Have a good day.
Execution from server side
$ cc ./server.c -o server
$ ./server
Connected to client
Sending file /home/username/Documents/something.txt
Sending Hello there!
Successfully sent
Sending Nice to meet you.
Successfully sent
Sending This is a text file.
Successfully sent
Sending Bye Bye :)
Successfully sent
Sending Have a good day.
Successfully sent
File transfer complete
This was the output I got from the server-side. This is weird because on client-side I didn't receive any message
$ cc ./client.c -o client
$ ./client
Connected to server
Receiving file something.txt
File transfer complete
The while loop in client side did not execute at all (because the data within buffer wasn't printed) and the read function did not return -1 otherwise a proper message would have been displayed.
This exact client code only works sometimes and other times it doesn't. What's the problem here?

UNIX Domain Socket programming 3 sockets

I am trying to make a server.c file that supports 3 sockets, which are represented by 3 respective client classes: client1, client2, client3.
In my server.c file, I currently have this code which I found on the internet.
If I wanted to make it have 3 sockets. I want to use the select() command to see the write activities of the 3 clients. My question is how can I use this to support 3 sockets.
Can I bind the 3 clients to 3 sockets that the server can listen to? If so, how can the server listen to these 3 sockets respectively? With an array possibly?
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#define socket1 "sock1"
#define socket2 "sock2"
#define socket3 "sock3"
int main(int argc, char *argv[]) {
//struct sockaddr_un addr;
struct sockaddr_un addr1;
struct sockaddr_un addr2;
struct sockaddr_un addr3;
char buf[100];
int socket1;
int socket2;
int socket3;
//int fd;
int cl,rc;
if (argc > 1) socket_path=argv[1];
if ( (socket1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr1, 0, sizeof(addr1));
addr1.sun_family = AF_UNIX;
strncpy(addr1.sun_path, socket_path, sizeof(addr1.sun_path)-1);
unlink(socket_path1);
if ( (socket2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr2, 0, sizeof(addr2));
addr1.sun_family = AF_UNIX;
strncpy(addr2.sun_path, socket_path, sizeof(addr2.sun_path)-1);
unlink(socket_path2);
if ( (socket3 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr3, 0, sizeof(addr3));
addr3.sun_family = AF_UNIX;
strncpy(addr3.sun_path, socket_path, sizeof(addr3.sun_path)-1);
unlink(socket_path3);
if (bind(socket1, (struct sockaddr*)&addr1, sizeof(addr1)) == -1) {
perror("bind error");
exit(-1);
}
if (bind(socket2, (struct sockaddr*)&addr2, sizeof(addr2)) == -1) {
perror("bind error");
exit(-1);
}
if (bind(socket3, (struct sockaddr*)&addr3, sizeof(addr3)) == -1) {
perror("bind error");
exit(-1);
}
if (listen(socket1, 5) == -1) {
perror("listen error");
exit(-1);
}
if (listen(socket2, 5) == -1) {
perror("listen error");
exit(-1);
}
if (listen(socket3, 5) == -1) {
perror("listen error");
exit(-1);
}
while (1) {
if ( (cl = accept(fd, NULL, NULL)) == -1) {
perror("accept error");
continue;
}
while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
printf("read %u bytes: %.*s\n", rc, rc, buf);
}
if (rc == -1) {
perror("read");
exit(-1);
}
else if (rc == 0) {
printf("EOF\n");
close(cl);
}
}
return 0;
}
If you want three listening sockets in the same process, you have to make them unique. In the AF_INET family you do that by bind(2)-ing different ports, in the AF_UNIX family you do that with different paths.
Also your line:
char *socket_path = "\0hidden";
has at least two problems:
Type of the string literal on the right side of the assignment is const char[8], which decays to const char* pointer type, but not char* type. Make the left hand side const char*. Plus, compile with higher warning level, like -Wall -pedantic to get help from your compiler.
Zero byte at the beginning of the string makes strncpy(3) not copy anything, since it copies at most n characters from the string pointed to by src, including the terminating null byte ('\0').
Create a function that take UNIX path as an argument and creates, binds, and marks socket as listening, and returns created socket descriptor. Call it three times - you have three listening UNIX sockets. Setup select(2) on them for reading - that'll tell you when client connections arrive. At that point call accept(2) on the active socket to get connected client socket, which is separate from the listening socket itself.
Ok, since select, is and has always been my favorite Unix syscall, I decided to do a little something, which is, in my humble opinion, what you were looking for.
I shamelessly took server's and client's code from here:
https://troydhanson.github.io/misc/Unix_domain_sockets.html
I did of course some little modifications, to make it fit your needs, lets see:
server.c:
#include <stdio.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
char *socket_path = "/tmp/socket";
int main() {
int fd, i;
int clients[10], num_clients;
fd_set read_set;
char buf[100];
struct sockaddr_un addr;
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
unlink(socket_path);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
if (listen(fd, 5) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
while (1) {
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) {
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd, NULL, NULL)) == -1) {
perror("accept error");
continue;
}
printf("we got a connection!\n");
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
read(clients[i], buf, sizeof(buf));
printf("client %d says: %s\n", i, buf);
}
}
}
}
client.c:
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char *socket_path = "/tmp/socket";
int main(int argc, char *argv[]) {
struct sockaddr_un addr;
char buf[100];
int fd,rc;
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("connect error");
exit(-1);
}
while( (rc=read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
printf("writing\n");
*index(buf, '\n') = 0;
if (write(fd, buf, rc) != rc) {
if (rc > 0) fprintf(stderr,"partial write");
else {
perror("write error");
exit(-1);
}
}
}
return 0;
}
Ok, this works very easily, you just fire the server in one terminal, and then you open a couple other terminals and fire a couple clients.
Running it on my pc I get:
exe#atreides:~/tmp$ ./server
we got a connection!
client 0 says: Hello!
we got a connection!
client 1 says: Hey man!
Another terminal at the same time:
exe#atreides:~/tmp$ ./client
Hey man!
writing
And in another:
exe#atreides:~/tmp$ ./client
Hello!
writing
The magic behind all this is to properly use socket and select.
First you need a server socket, the one that will accept connections.
Once you bind to a server socket, let it be a Unix socket or a network socket, you can get sockets to your clients by accepting connections on that socket. Each client gets a new socket number.
Then, you add these sockets, the server socket and the clients socket to an fd_set and pass it to select. Select will listen on all sockets at the same time and will leave in the set those who have received data.
Now you iterate the set to see what sockets are hot and, you're there!
One more thing, which I guess was confusing you, all clients connect to the same server socket address (file). Yes it is like if many processes opened the same file, at the same time... But this isn't an ordinary file, it is a Unix socket. :)
Have fun and good luck!!!

Unix Domain Socket Code Fails on Embedded Device

I've added a Unix domain socket to a project I'm working on. The socket has a simple function, it simply broadcasts data that the code extracts from another device, the idea is that other applications will be able to read this data from the socket.
I've written a simple server code, and when I run the code on my laptop, using a Ubuntu 10.04 VM, it works perfectly well. However, when I copy the code over onto the embedded device I'm using the code fails, when my application tries to write to the socket the code exits.
In /var/log/messages I see the following messages:
Dec 2 15:12:17 box local1.info my-app[17338]: Socket Opened
Dec 2 15:12:17 box local1.err my-app[17338]: Socket Failed
Dec 2 15:12:17 box local1.err my-app[17338]: Protocol wrong type for socket
Dec 2 15:12:38 box local1.info ./server[17178]: accept failed: Invalid argument
Here is the server code:
#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include<syslog.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BUF_SIZE 256 //Max length of string listened to
#define BACKLOG 5
int main(int argc, char *argv[]){
struct sockaddr_un addr;
int sfd, cfd; //File Descriptors for the server and the client
ssize_t numRead; //Length of the string read from the client.
u_int8_t buf[BUF_SIZE]; //String that reads messages
char plain[BUF_SIZE]; //Plain string for writing to the log
memset(plain, 0, sizeof plain); //blank out plain string
openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //Write the messages to the syslog
//---Declare socket--------------------------------------
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd!=0){
syslog(LOG_INFO, "socket success");
}
else{
syslog(LOG_INFO, "socket unsuccessful");
}
//--Test to see if there's already a socket at SV_SOCK_PATH, and remove it if there is.
if (remove(SV_SOCK_PATH) == -1 && errno !=ENOENT){
syslog(LOG_INFO, "error removing socket");
}
//-----------------------------------------------------------
//--blank out the socket address, then write the information to it
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path)-1); //ensure path is null terminated
//----Bind the socket to the address-------------------------------------
if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))!=0){
syslog(LOG_INFO, "bind unsuccessful");
}
else{
syslog(LOG_INFO, "bind successful");
}
//------------------------------------------------------------------------
//-----Listen on the socket-----------------------------------------------
if (listen(sfd, BACKLOG) != 0){
syslog(LOG_INFO, "listen failed");
}
else{
syslog(LOG_INFO, "listen succeeded");
}
//-------------------------------------------------------------------------
//--------Accept messages on the socket------------------------------------
socklen_t csize;
while(1){
cfd = accept(sfd, (struct sockaddr *)&addr,&csize);
if (cfd < 0) {
syslog(LOG_INFO, "accept failed: %s", strerror(errno));
}
while ( (numRead=read(cfd, buf, BUF_SIZE)) > 0 ){
dump_packet(buf, numRead);
}
}
//-------------------------------------------------------------------------
//---code never gets here but this is how to close the log and the socket--
closelog();
close(cfd);
}
And here's a simple version of the client that connects to this server from my app:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BACKLOG 5
int isDaemon = 1;
void etmlog(int level, char *message)
{
isDaemon == 1 ? syslog(level, message) : printf(message);
}
int main(){
struct sockaddr_un addr;
unsigned int sockfd;
ssize_t numRead;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0) {
etmlog(LOG_INFO, "Socket Opened\n");
}
else {
etmlog(LOG_ERR, "Socket Failed:\n");
etmlog(LOG_ERR, strerror(errno));
exit(-1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1); // -1 ensures null terminated string
if (connect
(sockfd, (struct sockaddr *)&addr,
sizeof(struct sockaddr_un)) == -1) {
etmlog(LOG_ERR, "Socket Failed\n");
etmlog(LOG_ERR, strerror(errno));
exit(1);
} else {
etmlog(LOG_INFO, "Socket Connection Successful\n");
}
while (1){
// some data is read into buf up here
if (write(sockfd, buf, rdlen) < 0) {
etmlog(LOG_ERR, "Write to Socket Failed:");
etmlog(LOG_ERR, strerror(errno));
}
}
close(sockfd);
return 0;
}
I appreciate that I've just posted a lot of code to read through, but I'd be very grateful if someone could give me a few pointers on this.
You are not using accept correctly. The third argument must be initialized to the size of the second argument, so that accept won't overflow it. See man accept.

berkeley sockets, running simple client and server connecting

I'm just starting out on networking programming in c. I followed a simple tutorial to create a server which accepts a connection and prints out the message sent from the client.
the client takes an argument as the address of the server.
I'm not sure how to specify the address of the server? Is it my machine name?
I'm running the server in one terminal and trying to connect from another. Thanks for any help :)
here's the server code
`#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
#define BUFLEN 1500
int fd;
ssize_t i;
ssize_t rcount;
char buf[BUFLEN];
printf("test1");
fd = socket (AF_INET,SOCK_STREAM,0);
if (fd == -1){
printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
}
struct sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(500);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
printf("cannot bind socket");
}
if (listen(fd, 20) == -1) {
printf("unable to listen");
}
int connfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
printf("unable to accept");
}
rcount = read(fd, buf, BUFLEN);
if (rcount == -1) {
// Error has occurred
}
for (i = 0; i < rcount; i++) {
printf("%c", buf[i]);
}
}`
printf("test1");
You should add "\n" (newline char) at the end of printed string, so that it prints immediately. Without "\n", printf() buffers its output, and you don't see them.
addr.sin_port = htons(500);
Ports 0 - 1023 are called "well known port" and reserved to the system (root). You should use port 1024 or greater for a test program like this. Changing it from 500 to 1500 (for example) binds successfully.
(You don't see the error message "cannot bind socket" because it has no "\n", as I said above.)
rcount = read(fd, buf, BUFLEN);
You should read from connfd, instead of fd. With these changes, it worked for me.
(I used "telnet localhost 1500" as a client.)

C Socket Programming: HTTP request not working continously

I am a newbie to c socket programming and c itself. I have written a small piece of code that reads raw input from another internet socket and post the data to a webserver. the received data is always numeric. however the problem seems that the http post request happens only once instead of running in a loop and the program terminates.
following is the code example
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
//define server parameters
#define WEBIP "172.16.100.2"
int main()
{
//declare variables
struct sockaddr_in my_addr,client_addr,server_addr;
struct hostent *server_host;
int true=1;
int client_socket_id,server_socket_id;
int client_id;int sin_size;
int client_bytes_received;
char send_data [1024],recv_data[1024],post_data[1024];
server_host=gethostbyname(WEBIP2);
//create a socket to listen to client
if ((client_socket_id = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error Creating Socket");
exit(1);
}
if (setsockopt(client_socket_id,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
//create socket to connect to webserver
if ((server_socket_id = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error Creating Webserver Socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(7070);
my_addr.sin_addr.s_addr = INADDR_ANY;
//bzero(&(my_addr.sin_zero),8);
bzero(&(server_addr.sin_zero),8);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(WEBPORT);
server_addr.sin_addr = *((struct in_addr *)server_host->h_addr);
//bind to a socket
if (bind(client_socket_id, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1) {
perror("Unable to bind");
exit(1);
}
//listen to socket
if (listen(client_socket_id, 5) == -1) {
perror("Error Listening to Socket");
exit(1);
}
printf("\n\r Waiting for client on port 7070");
fflush(stdout);
while(1)
{
sin_size = sizeof(struct sockaddr_in);
client_id = accept(client_socket_id, (struct sockaddr *)&client_addr,&sin_size);
printf("\n I got a connection from (%s , %d)",
inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
//connect to remote server
if (connect(server_socket_id, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
{
perror("Error Connecting to Web Server");
exit(1);
}
while(1){
//send some data to client
send(client_id,"Hello, World!",13, 0);
//receive some data from client
client_bytes_received=recv(client_id,recv_data,1024,0);
recv_data[client_bytes_received] = '\0';
//print received_data
int c_length=strlen(recv_data)+11;
printf("\n\rRecieved data (%d bytes %d words)= %s " , client_bytes_received,c_length,recv_data);
//post dta to webserver
fflush(stdout);
bzero(&post_data,1024);
sprintf(post_data,"POST /environment.php HTTP/1.1\r\n"
"Host: 172.16.100.2\r\n"
"User-Agent: C Example Client\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %d\r\n\r\n"
"track_data=%s",c_length,recv_data);
write(server_socket_id,post_data,strlen(post_data)+1);
bzero(&recv_data,1024);
while((client_bytes_received=read(server_socket_id,recv_data,1024))>0){
recv_data[client_bytes_received] = '\0';
if (fputs(recv_data,stdout)==EOF)
perror("web server read_error");
}
//print received_data
printf("\n\rRecieved data from webserver (%d)= %s " , client_bytes_received,recv_data);
//
bzero(&recv_data,1024);
fflush(stdout);
}
}
close(client_id);
close(client_socket_id);
return 0;
}
I have not done socket programming for years, so please bear with me. Do you need to connect, process, and then disconnect? That's the first thing that came to mind reading your code.
I am surprised this program works. You have created blocking sockets, unless you are working on a non-POSIX compliant OS. The accept call should have never returned. If accept is returning it means that your server socket is not able to go into the wait mode. Hence whatever you are seeing is most likely because of an error.
SO_NONBLOCK is the socket option you can use for creating non blocking sockets.
Since you are using the same routine for both client and server you should use select in the socket loop.

Resources