This question has been asked many times, but searching through and implementing some solutions that have worked for others, I still haven't been able to figure out what I'm doing wrong. I am still having issues understanding programming with sockets, so any explanations would be greatly appreciated. The function where I am getting the error is "int forwardClientReq(char* buffer, char* hostname, int clientfd)" and more specifically around this:
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
The full code is as follows:
/* Proxy application called webproxy */
// Copy past http server includes, remove unnecessary
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for fgets */
#include <strings.h> /* for bzero, bcopy */
#include <unistd.h> /* for read, write */
#include <sys/socket.h> /* for socket use */
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#define MAXBUF 8192 /* max text line length */
#define LISTENQ 1024 /* second argument to listen() */
#define ERRBUFSIZE 1024
#define HEAPBUF 32768 // 2^15
int open_listenfd(int port);
void webProxy(int connfd);
void *thread(void *vargp);
int connect2Client(char* ip, char* port);
void sendErrResponse(char* errBUF, int connfd);
int forwardClientReq(char* buffer, char* host, int clientfd);
int main(int argc, char **argv)
{
int timeout = 0;
/* Check if the function was called correctly */
/* Store arguments provided (port number & cache timeout) */
if(argc < 2 || argc > 3){
fprintf(stderr, "Incorrect arguments, Usage: ./<executableFile> <port#> <timeout(optional)>\n");
exit(0);
}
if(argc == 3)
timeout = atoi(argv[2]);
int listenfd, *connfdp, port, clientlen=sizeof(struct sockaddr_in);
pthread_t tid;
struct sockaddr_in clientaddr;
port = atoi(argv[1]); // store the port number
listenfd = open_listenfd(port); // create persistant TCP socket for client HTTP requests
/* Create,Bind,Listen SOCKET and multithread */
while (1) {
connfdp = malloc(sizeof(int)); // pointer to pass the socket
*connfdp = accept(listenfd, (struct sockaddr*)&clientaddr, &clientlen);
if(*connfdp<0)
printf("There is an error accepting the connection with the client");
pthread_create(&tid, NULL, thread, connfdp); // call thread function with tid
}
}
/* thread routine */
void * thread(void * vargp)
{
int connfd = *((int *)vargp);
pthread_detach(pthread_self());
free(vargp);
webProxy(connfd);
close(connfd);
return NULL;
}
void webProxy(int connfd)
{
size_t n;
char buffer[MAXBUF]; // pointer to pass the socket
char errorBuf[ERRBUFSIZE];
bzero(errorBuf, ERRBUFSIZE);
bzero(buffer, MAXBUF);
char httpmsg[]="HTTP/1.1 200 Document Follows\r\nContent-Type:text/html\r\nContent-Length:32\r\n\r\n<html><h1>Hello CSCI4273 Course!</h1>";
char hostname[50];
n = read(connfd, buffer, MAXBUF); // read the requst up to maxbuf sizeof
printf("server received the following request:\n%s\n",buffer);
/* parse the request */
char requestType[50], fullPath[50];
bzero(requestType, 50);
bzero(fullPath, 50);
sscanf(buffer, "%s %s", requestType, fullPath);
printf("requestType = %s, and fullPath= %s\n", requestType, fullPath);
/* I tried a million different methods and libary suggestions but this is the only
method that I found to easily parse the information I wanted to input */
// sscanf(fullPath, "http://www.%511[^/\n]", hostname);
sscanf(fullPath, "http://%511[^/\n]", hostname);
printf("hostname is = %s\n", hostname);
/* support only GET requests */
if(strcmp(requestType, "GET") != 0)
{
printf("Proxy received a request that was not a 'GET' Request, sending 400 Bad Request response\n");
sendErrResponse(errorBuf, connfd);
}
// // /* support only HTTP/1.1 */
// else if(strcmp(Type, "HTTP/1.1") != 0)
// {
// printf("Proxy received a request that was not an HTTP/1.1 version, sending 400 Bad Request response");
// // I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
// sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
// write(connfd, errorBuf, strlen(errorBuf));
// bzero(errorBuf, ERRBUFSIZE);
// }
/* parse and verify the hostname/server */
struct hostent *host = gethostbyname(hostname);
if (host == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
sendErrResponse(errorBuf, connfd);
exit(0);
}
else{
/* Forward request to HTTP server */
forwardClientReq(buffer, hostname, connfd);
printf("buffer = %s\n", buffer);
/* Relay data from server to client */
}
}
int forwardClientReq(char* buffer, char* hostname, int clientfd)
{
char* serverResponse = malloc(HEAPBUF); // create a buffer for receiving the response from the server
bzero(serverResponse, HEAPBUF); // zeroize the buffer
/* open a socket with the server */
struct sockaddr_in serveraddr;
int serverSock, optval =1;
/* Create a socket descriptor */
if(-1 == (serverSock = socket(AF_INET, SOCK_STREAM, 0))) // yoda condition...
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0){
printf("Error in setsockopt in forwardClientReq function");
return -1;
}
struct hostent* host = gethostbyname(hostname);
serveraddr.sin_family = AF_INET;
memcpy(&serveraddr.sin_addr, host->h_addr_list[0], host->h_length);
serveraddr.sin_port = htons(80); //(you should pick the correct remote port or use the default 80 port if noneis specified).
socklen_t addrlen = sizeof(serveraddr); // The addrlen argument specifies the size of serveraddr.
int serverfd = connect(serverSock, (struct sockaddr*) &serveraddr, addrlen);
if(serverfd < 0)
printf("improper connection when trying to forward client's request/n");
/* send the client message to the server */
int numBytesSent = 0;
printf("buffer before send = %s\n", buffer);
sprintf(buffer, "\r\n\r\n");
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
// printf("Sent %d to the server", numBytesSent);
// /* store the server's response */
// int numBytesRead = 0;
// numBytesRead = read(serverfd, serverResponse, HEAPBUF);
// printf("Sent %d to the server", numBytesRead);
//
// /* send the response to the client. This is a moment here the proxy can cache the page,
// inspect the data, and do all kinds of cool proxy-level things */
// numBytesSent = write(clientfd, serverResponse, strlen(serverResponse));
// printf("Sent %d to the server", numBytesSent);
free(serverResponse); // free malloc'd space
}
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0)
return -1;
/* listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
/* bind: associate the parent socket with a port */
if (bind(listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
} /* end open_listenfd */
void sendErrResponse(char* errorBuf, int connfd)
{
// I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
write(connfd, errorBuf, strlen(errorBuf));
bzero(errorBuf, ERRBUFSIZE);
}
The return value of connect is an error code not a socket fd:
If the connection or binding succeeds, zero is returned. On error,
-1 is returned, and errno is set appropriately.
So
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
Should be
numBytesSent = send(serverSock, buffer, strlen(buffer), 0);
Related
I have a C script that connects to a remote server with a socket and writes a command.
I have to do this as fast as possible and i need to switch from source ip addressess. The problem is, when i switch from ip addresses, the bind slows down for seconds.
I can not find a solution.
the code:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in source, destination = {}; //two sockets declared as previously
int sock = 0;
int n = 0;
int datalen = 0;
int pkt = 0;
char* ips[3] = {"10.0.0.1", "10.0.0.2", "10.0.0.3"};
uint8_t *send_buffer;
char recv_buffer[11];
struct sockaddr_storage fromAddr; // same as the previous entity struct sockaddr_storage serverStorage;
unsigned int addrlen; //in the previous example socklen_t addr_size;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/*Inititalize source to zero*/
memset(&source, 0, sizeof(source)); //source is an instance of sockaddr_in. Initialization to zero
/*Inititalize destinaton to zero*/
memset(&destination, 0, sizeof(destination));
/* setting the destination, i.e our OWN IP ADDRESS AND PORT */
destination.sin_family = AF_INET;
// destination.sin_addr.s_addr = inet_addr("123.456.789.123");
destination.sin_port = htons(43);
/*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
/* Address family = Internet */
source.sin_family = AF_INET;
/* Set IP address to localhost */
// source.sin_addr.s_addr = INADDR_ANY;
/* Set port number, using htons function to use proper byte order */
source.sin_port = htons(43);
/* Set all bits of the padding field to 0 */
memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional
int i;
for (i=0; i<60; i++) {
/* creating the socket */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Failed to create socket\n");
/*set the socket options*/
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
if(inet_pton(AF_INET, ips[i%3], &source.sin_addr)<=0) //this is where is switch the ip addresses
{
printf("\n inet_pton error occured\n");
return 1;
}
/*bind socket to the source WHERE THE PACKET IS COMING FROM*/
if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0)
printf("Failed to bind socket");
if(inet_pton(AF_INET, "94.198.154.139", &destination.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if(connect(sock, (struct sockaddr *)&destination, sizeof(destination)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
printf("check\n");
n = write(sock,"is liveresults.nl\r\n",21);
if (n < 0) error("ERROR writing to socket");
while ( (n = read(sock, recv_buffer, sizeof(recv_buffer)-1)) > 0)
{
recv_buffer[n] = 0;
if(fputs(recv_buffer, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
close(sock);
}
return 0;
}
edit: i must notice that it slows down afther the first loops for every ip. Because i have 3 ip addresses. After the first round, it slow down for seconds per bind.
I have to bind the local port to 0 instead of the same port as the outgoing port.
I am trying to implement TCP client, server program in C on Linux system. Here are my codes.
Client Source Code :
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char *address;
// Create socket
int client_socket;
client_socket = socket(AF_INET, SOCK_STREAM, 0);
// Set - Up Server Address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
inet_aton(address, &server_address.sin_addr.s_addr);
// Connect to the server
int connect_stat;
connect_stat = connect(client_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if(connect_stat == -1)
printf("Not Connected\n");
else
printf(" Connected \n");
// Recieve from server
char response[256];
recv(client_socket, &server_address, sizeof(server_address), 0);
// Printing the Response data
printf("Data Recieved : %s\n",response);
// Destroy the socket
close(client_socket);
return 0;
}
Server Source Code :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// Address
char *address;
address = argv[1];
// Create message to send
char message[256] = "Connection Established";
// Create server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// Set - Up Server Address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
inet_aton(address, &server_address.sin_addr.s_addr);
// Bind it to an IP and PORT
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
// Start listenting on address
listen(server_socket, 5);
// Start accepting the clients;
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
// Send some data back to client
send(client_socket, message, sizeof(message), 0);
// Close the socket
close(server_socket);
close(client_socket);
return 0;
}
On passing an IP like 192.168.1.xxx to both client and server, server starts waiting for the clients but client always show not connected and thus no data received.
Client output :
root#kali:/home/mayank/Desktop/tcp_chat# ./tcp_client 192.168.1.111
Not Connected
Data Recieved :
But if i use INADDR_ANY instead of specific IP, it works. I know INADDR_ANY basically means it binds to all IP address, but why it is not binding to specific IP address which i want. Any suggestions, where i am wrong.
Instead of inet_aton(), you can also use
server_address.sin_addr.s_addr = inet_addr("IP address");
And use perror() after every function, like
client_socket = socket(...);
if (client_socket == -1)
perror("socket");
You are not doing any error checking, except on the connect() call. For example, you are getting an ENOTSOCK error because you are not checking whether socket() succeeds or fails.
Beyond that, on the client side, this statement:
inet_aton(address, &server_address.sin_addr.s_addr);
Should be this instead:
inet_aton(address, &server_address.sin_addr);
inet_aton() expects a pointer to a struct in_addr, but you are passing it a pointer to a uint32_t instead. In fact, the original code should not have even compiled because of that.
But, more importantly, your address variable is uninitialized, so you are passing a bad memory pointer to inet_aton(), and not checking its return value for failure.
Even if you could connect to the server, you are also passing the wrong output buffer to recv(), so you would end up writing garbage to the console.
Try this instead:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("usage: %s <IPv4 address>\n", argv[0]);
return 0;
}
// Set - Up Server Address
struct sockaddr_in server_address = {0};
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
if (inet_aton(argv[1], &server_address.sin_addr) != 0)
{
printf("invalid IPv4 address specified\n");
return 0;
}
// Create socket
int client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket == -1)
{
perror("socket() failed");
return 0;
}
// Connect to the server
if (connect(client_socket, (struct sockaddr *) &server_address, sizeof(server_address)) == -1)
{
perror("Not Connected");
}
else
{
printf("Connected\n");
// Receive from server
char response[256];
int numRecvd = recv(client_socket, response, sizeof(response), 0);
// Printing the Response data
if (numRecvd == -1)
perror("recv() failed");
else if (numRecvd == 0)
printf("Disconnected by server\n");
else
printf("Data Received: [%d] %.*s\n", numRecvd, numRecvd, response);
}
// Destroy the socket
close(client_socket);
return 0;
}
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// Set - Up Server Address
struct sockaddr_in server_address = {0};
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
if (argc >= 2)
{
if (inet_aton(argv[1], &server_address.sin_addr) != 0)
{
printf("invalid IPv4 address specified\n");
return 0;
}
}
else
server_address.sin_addr.s_addr = INADDR_ANY;
// Create message to send
char message[256] = "Connection Established";
// Create server socket
int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == -1)
{
perror("socket() failed");
return 0;
}
// Bind it to an IP and PORT
if (bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) == -1)
{
perror("bind() failed");
}
// Start listenting on address
else if (listen(server_socket, 5) == -1)
{
perror("listen() failed");
}
// Start accepting the clients
else
{
int client_socket = accept(server_socket, NULL, 0);
if (client_socket == -1)
{
perror("accept() failed");
}
else
{
// Send some data back to client
int numSent = send(client_socket, message, sizeof(message), 0);
if (numSent == -1)
perror("send() failed");
else
printf("Data Sent: [%d] %.*s\n", numSent, numSent, message);
// Close the socket
close(client_socket);
}
}
// Destroy the socket
close(server_socket);
return 0;
}
As i already asked similar questions but didn't get a solution. Hence i put this problem again with the whole code. Please tell me how can i acheive this goal
1) i have a client which sends to mainserver (127.0.0.1) a message and main server forwards it to server2 (127.0.0.2)
2) Server2 sends a message to the mainserver and mainserver forwards it to client.
Problem 1) : Although i receive the datas from client but they are not sent to server2.
Problem 2) :I dont receive any data from server2
//SERVER
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>//use select() for multiplexing
#include <sys/fcntl.h> // for non-blocking
#define MAX_LENGTH 100000
#define PORT 1901
/* Select() params
* int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
* FD_SET(int fd, fd_set *set);
* FD_CLR(int fd, fd_set *set);
* FD_ISSET(int fd, fd_set *set);
* FD_ZERO(fd_set *set);
*/
void error(char *message)
{
perror(message);
exit(1);
}
int main()
{
// select parameters declared
fd_set original_socket;
fd_set original_stdin;
fd_set readfds;
fd_set writefds;
struct timeval tv;
int numfd, numfd2;
// socket parameters declared
int socket_fd_ob, socket_fd_hm;
int bytes_read, bytes_sent;
char address_length, address_length2;
char recieve_data[MAX_LENGTH];
char send_data[MAX_LENGTH];
struct sockaddr_in server_address_ob, server_address_hm, client_address;
int z = 0;
//Socket creation done separately for both OBCU and HM communications
if ((socket_fd_ob = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
if ((socket_fd_hm = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
fcntl(socket_fd_ob, F_SETFL, O_NONBLOCK); //set socket to non-blocking
fcntl(socket_fd_hm, F_SETFL, O_NONBLOCK); //set socket to non-blocking
// clear the set ahead of time
FD_ZERO(&original_socket);
FD_ZERO(&original_stdin);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptors to the set (0 - stands for STDIN)
FD_SET(socket_fd_ob, &original_socket);//instead of 0 put socket_fd_ob
FD_SET(socket_fd_ob, &readfds);
FD_SET(0,&original_stdin);
FD_SET(0, &writefds);
// the n param in select()
numfd = socket_fd_ob + 1;
numfd2 = socket_fd_hm + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 0.7;
tv.tv_usec = 500000;
server_address_ob.sin_family = AF_INET;
server_address_ob.sin_port = htons(1901);
server_address_ob.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_ob));
server_address_hm.sin_family = AF_INET;
server_address_hm.sin_port = htons(1901);
server_address_hm.sin_addr.s_addr = inet_addr("127.0.0.2");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_hm));
// Bind socket to the particular addresses
if (bind(socket_fd_ob,(struct sockaddr *)&server_address_ob, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
if (bind(socket_fd_hm,(struct sockaddr *)&server_address_hm, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
address_length = sizeof(struct sockaddr);
address_length2 = sizeof(struct sockaddr);
printf("\nMain server waiting for client to respond...\n");
fflush(stdout);
while (1)
{
readfds = original_socket;
writefds = original_stdin;//problem
int recieve = select(numfd, &readfds, &writefds,/*NULL,*/ NULL, &tv);
int sent = select(numfd2, &readfds, &writefds,/*NULL,*/ NULL, &tv);
if (recieve == -1 || sent == -1)
{
perror("select"); // error occurred in select()
}
else if (recieve == 0 || sent == 0)
{
printf("Timeout occurred! No data after 1.5 seconds.\n");
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(socket_fd_ob, &readfds)) //if set to read
{
FD_CLR(socket_fd_ob, &readfds);
if (bytes_read = recvfrom(socket_fd_ob,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&server_address_ob, &address_length)>0)
{
for (z = 0; z < bytes_read; ++z) {
FD_ISSET(socket_fd_hm, &writefds);
FD_CLR(socket_fd_hm, &writefds);
//recvfrom speech recognition client and decide what to send to HM accordingly..
send_data[bytes_read] = recieve_data[bytes_read];
//block call, will wait till client enters something, before proceeding
//send the corresponding to HM
bytes_sent = sendto(socket_fd_hm,send_data,strlen(send_data)+1,0,(struct sockaddr *)&server_address_hm, &address_length2);
fflush(stdout);
}
// 02x, #x,X
printf("\n(%s , %d) rcvd: %s\n",inet_ntoa(server_address_ob.sin_addr),ntohs(server_address_ob.sin_port),recieve_data);
printf("\n(%s , %d) sent: %s\n",inet_ntoa(server_address_hm.sin_addr),ntohs(server_address_hm.sin_port),send_data);
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
send_data[bytes_read] = '\0'; //add null to the end of the buffer
}
else if (bytes_read = recvfrom(socket_fd_hm,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&server_address_hm, &address_length)>0)
{
for (z = 0; z < bytes_read; ++z) {
FD_ISSET(socket_fd_ob, &writefds);
FD_CLR(socket_fd_ob, &writefds);
send_data[bytes_read] = recieve_data[bytes_read];
//block call, will wait till client enters something, before proceeding
//send the corresponding to HM
bytes_sent = sendto(socket_fd_ob,send_data,strlen(send_data)+1,0,(struct sockaddr *)&server_address_ob, &address_length2);
fflush(stdout);
}
// 02x, #x,X
printf("\n(%s , %d) rcvd: %s\n",inet_ntoa(server_address_hm.sin_addr),ntohs(server_address_hm.sin_port),recieve_data);
printf("\n(%s , %d) sent: %s\n",inet_ntoa(server_address_ob.sin_addr),ntohs(server_address_ob.sin_port),send_data);
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
send_data[bytes_read] = '\0'; //add null to the end of the buffer
}
else
{
printf("error noted");
}
} //end if set to read
} //end else
}//end while
close (socket_fd_ob);
close (socket_fd_hm);
return 0;
}
Please suggest me with code samples. i am new to this topic and didn't have a broad view yet.
Thanks
I'm a new to socket programming. I tried to connect a server to multiple clients and i have two problems in it. 1)I can't send a message unless i get a reply i.e if a client connects and sends a message,client can't send a message again until it gets reply from server. If client types some message it stores the messages and it sends the message after it gets a reply.
2)I want to restrict the number of connections to 1 and if some one connects no one else should connect until the client the client quits. If the client quits the one who is first in waiting should be connected.
server
#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>
#define MYPORT 3490 /* the port users connect to */
#define BACKLOG 0 /* max no. of pending connections in server queue */
#define MAXDATASIZE 200
void sigchld_handler(int s)
{
while( wait( NULL) > 0); /* wait for any child to finish */
}
int main( void)
{
int listenfd;
/* listening socket */
int connfd;
/* connection socket */
struct sockaddr_in server_addr; /* info for my addr i.e. server */
struct sockaddr_in client_addr; /* client's address info */
int sin_size;
/* size of address structure */
struct sigaction sa; /* deal with signals from dying children! */
int yes = 1;
char clientAddr[ 20]; /* holds ascii dotted quad address */
if ((listenfd = socket( AF_INET, SOCK_STREAM, 0)) == -1)
{
perror( "Server socket");
exit( 1);
}
/* Set Unix socket level to allow address reuse */
if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,&yes, sizeof( int)) == -1)
{
perror( "Server setsockopt");
exit( 1);
}
sin_size = sizeof( server_addr);
memset( &server_addr, 0, sin_size);
/* zero struct */
server_addr.sin_family = AF_INET;
/* host byte order ... */
server_addr.sin_port = htons( MYPORT); /* . short, network byte order */
server_addr.sin_addr.s_addr = INADDR_ANY; /* any server IP addr */
if( bind( listenfd, (struct sockaddr *)&server_addr,sizeof( struct sockaddr)) == -1)
{
perror( "Server bind");
exit( 1);
}
if( listen( listenfd, BACKLOG) == -1)
{
perror( "Server listen");
exit( 1);
}
/* Signal handler stuff */
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( "Server sigaction");
exit( 1);
}
while( 1)
{
/* main accept() loop */
sin_size = sizeof( struct sockaddr_in);
if( (connfd = accept( listenfd,(struct sockaddr *)&client_addr, &sin_size)) == -1)
{
perror( "Server accept");
continue;
}
strcpy( clientAddr, inet_ntoa( client_addr.sin_addr));
printf( "Server: got connection from %s\n", clientAddr);
if( !fork())
{
/* the child process dealing with a client */
char msg[ MAXDATASIZE];
int numbytes;
close( listenfd); /* child does not need the listener */
msg[ 0] = '\0';
/* no message yet! */
do
{
if( (numbytes =recv( connfd, msg, MAXDATASIZE -1, 0)) == -1)
{
perror( "Server recv");
exit( 1);
/* error end of child */
}
msg[ numbytes] = '\0';
/* end of string */
fprintf( stderr, "Message received: %s\n", msg);
do
{
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
printf( "Message to send: ");
scanf( "%s", msg);
if( send( connfd, msg, strlen( msg), 0) == -1)
{
perror( "server send");
//exit(1);
}
/* error end of child */
}
while( strcmp( msg, "quit") != 0);
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
//close( connfd);
//exit(0);
/* end of child! */
}
while(1);
//fork();
//close(connfd); /* parent does not need the connection socket */
return 0;
}
}
}
client:
#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 <netdb.h>
/* for gethostbyname() */
#define PORT 3490
/* server port the client connects to */
#define MAXDATASIZE 100 /* max bytes to be received at once */</i>
int main( int argc, char * argv[])
{
int sockfd, numbytes;
char buf[ MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* server address info */
char msg[ MAXDATASIZE];
if( argc != 2) {
fprintf( stderr, "usage: client hostname\n");
exit( 1);
}
/* resolve server host name or IP address */
if( (he = gethostbyname( argv[ 1])) == NULL) { /* host server info */
perror( "Client gethostbyname");
exit( 1);
}
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
perror( "Client socket");
exit( 1);
}
memset( &their_addr, 0, sizeof( their_addr));
/* zero all */
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);
if( connect( sockfd, (struct sockaddr *)&their_addr,
sizeof( struct sockaddr)) == -1) {
perror( "Client connect");
exit( 1);
}
do {
printf( "Message to send: ");
scanf( "%s", msg);
if( (numbytes = send( sockfd, msg, strlen( msg), 0)) == -1) {
perror( "Client send");
continue;
}
if( (numbytes = recv( sockfd, buf, MAXDATASIZE - 1, 0)) == -1) {
perror( "Client recv");
continue;
}
buf[ numbytes] = '\0';
/* end of string char */
printf( "Received: %s\n", buf);
} while( strcmp( msg, "quit") != 0);
close( sockfd);
return 0;
}
dear you have to use multithreading for this start a new thread to handle new connection
in that thread also use separate threads for receiving data and sending data ...
1)I can't send a message unless i get a reply i.e if a client connects
and sends a message,client can't send a message again until it gets
reply from server.
That's no wonder, since you have programmed this sequential arrangement of scanf and recv in your client's do loop. To handle message input and socket receipt in order of appearance, we can use select; your do loop could then look like:
do
{ fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(sockfd, &fds); // set of descriptors holds stdin and socket
printf("Message to send: "), fflush(stdout);
if (select(sockfd+1, &fds, NULL, NULL, NULL) < 0) break; // error?
// see which descriptors of set are ready
if (FD_ISSET(STDIN_FILENO, &fds))
{ // it is the standard input
scanf("%s", msg);
numbytes = send(sockfd, msg, strlen(msg), 0);
if (numbytes == -1) perror("Client send");
}
if (FD_ISSET(sockfd, &fds))
{ // this is the peer's message or termination
numbytes = recv(sockfd, buf, MAXDATASIZE - 1, 0);
if (numbytes <= 0)
{
perror("Client recv");
break; // no more data from peer, so close the connection
}
buf[numbytes] = '\0'; /* end of string char */
printf("Received: %s\n", buf);
}
} while (strcmp(msg, "quit") != 0);
2)I want to restrict the number of connections to 1 and if some one
connects no one else should connect until the client the client quits.
We can achieve this simply by not forking a server process after we accept a client connection request, but rather handling the message transfer in the one and only server task itself (quite similar as shown above for the client); just omit the lines if( !fork()) as well as return 0; instead uncomment the close(connfd); and don't forget to break out of the do loop when recv returns a nonpositive value.
I received the error: `connect failed: connection refused` from the following code. Server side code runs fine, but when I run the client side I get the connect failed error. I am using Ubuntu.
server side run: `./server.out 1234`
client side run: `.client.out 127.0.0.1 input.txt 1234`
Client 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>
#include <arpa/inet.h>
//#include "Practical.h"
// check error
void DieWithError(char *errorMessage)
{
perror(errorMessage);
exit(1);
}
void DieWithUserMessage(const char *msg, const char *detail) {
fputs(msg, stderr);
fputs(": ", stderr);
fputs(detail, stderr);
fputc('\n', stderr);
exit(1);
}
void DieWithSystemMessage(const char *msg) {
perror(msg);
exit(1);
}
//define buffer size
enum sizeConstants {
MAXSTRINGLENGTH = 128,
BUFSIZE = 512,
};
int main(int argc, char *argv[]) {
char buffer[BUFSIZE];
//FILE *fp,*fpOut; // declare file pointer
if (argc < 3 || argc > 4) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)","<Server Address> <Echo Word> [<Server Port>]");
char *servIP = argv[1]; // First arg: server IP address (dotted quad)
char *echoString = argv[2]; // Second arg: string to echo
// Third arg (optional): server port (numeric). 7 is well-known echo port
in_port_t servPort = (argc == 4) ? atoi(argv[3]) : 7;
// Create a reliable, stream socket using TCP
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0)
DieWithSystemMessage("socket() failed");
// Construct the server address structure
struct sockaddr_in servAddr; // Server address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &servAddr.sin_addr.s_addr);
if (rtnVal == 0)
DieWithUserMessage("inet_pton() failed", "invalid address string");
else if (rtnVal < 0)
DieWithSystemMessage("inet_pton() failed");
servAddr.sin_port = htons(servPort); // Server port
// Establish the connection to the echo server
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("connect() failed");
/*
//start reading file input from computer
char buf[1000];
fp =fopen("input.txt","r");//open the file
if (!fp){
printf("it failed!\n");
return 1;
}
while(fgets (buf, 1000, fp)!=NULL) { // take the file input value in buf char array
//printf("The input value in program.txt file: %s",buf);
printf("Received Message from server: ");
*/
size_t echoStringLen = strlen(echoString); // Determine input length
// Send the string to the server
ssize_t numBytes = send(sock, echoString, echoStringLen, 0);
if (numBytes < 0)
DieWithSystemMessage("send() failed");
else if (numBytes != echoStringLen)
DieWithUserMessage("send()", "sent unexpected number of bytes");
// Receive the same string back from the server
unsigned int totalBytesRcvd = 0; // Count of total bytes received
// Setup to print the echoed string
while (totalBytesRcvd < echoStringLen) {
// I/O buffer
/* Receive up to the buffer size (minus 1 to leave space for
a null terminator) bytes from the sender */
numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
else if (numBytes == 0)
DieWithUserMessage("recv()", "connection closed prematurely");
totalBytesRcvd += numBytes; // Keep tally of total bytes
buffer[numBytes] = '\0'; // Terminate the string!
printf("%s",buffer);
//fputs(buffer, stdout); // Print the echo buffer
}
//fpOut = fopen("gcd.txt","w"); // open the gcd txt file in write mode
//fprintf(fpOut,"%s",buffer );// write the gcd value in gcd text file
//fputc('\n', stdout);
//fclose(fpOut);
//fclose(fp);
return 0;
close(sock);
exit(0);
}
Server code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include "Practical.h"
void DieWithError(char *errorMessage)
{
perror(errorMessage);
exit(1);
}
void DieWithUserMessage(const char *msg, const char *detail) {
fputs(msg, stderr);
fputs(": ", stderr);
fputs(detail, stderr);
fputc('\n', stderr);
exit(1);
}
void DieWithSystemMessage(const char *msg) {
perror(msg);
exit(1);
}
static const int MAXPENDING = 5; // Maximum outstanding connection requests
int main(int argc, char *argv[]) {
if (argc != 2) // Test for correct number of arguments
DieWithUserMessage("Parameter(s)", "<Server Port>");
in_port_t servPort = atoi(argv[1]); // First arg: local port
// Create socket for incoming connections
int servSock; // Socket descriptor for server
if ((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithSystemMessage("socket() failed");
// Construct local address structure
struct sockaddr_in servAddr; // Local address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
servAddr.sin_port = htons(servPort); // Local port
// Bind to the local address
if (bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0)
DieWithSystemMessage("bind() failed");
// Mark the socket so it will listen for incoming connections
if (listen(servSock, MAXPENDING) < 0)
DieWithSystemMessage("listen() failed");
for (;;) { // Run forever
struct sockaddr_in clntAddr; // Client address
// Set length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
printf("\nIam here\n");
// Wait for a client to connect
int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen);
if (clntSock < 0)
DieWithSystemMessage("accept() failed");
// clntSock is connected to a client!
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName,sizeof(clntName)) != NULL)
printf("Got response from client: %s/%d\n", clntName, ntohs(clntAddr.sin_port));
else
puts("Unable to get client address");
HandleTCPClient(clntSock);
}
// NOT REACHED
}
HandleTCPClient:`#define RCVBUFSIZE 1024 /* Size of receive buffer */
void DieWithError(char errorMessage); / Error handling function */
void HandleTCPClient(int clntSocket) {
FILE *fp;
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
int recvMsgSize; /* Size of received message */
/* Receive message from client */
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
printf("Server asked file name from Client side:: %s", echoBuffer);
fp =fopen("echoBuffer","r");//open the file
if (!fp){
printf("it failed!\n");
//return 1;
}
//int i,j;
//sscanf(echoBuffer, "%d %d", &i,&j);// take the two number from client and convert string to integer.
//sprintf(echoBuffer,"%d",gcd(i,j)); // call the gcd method.
/* Send received string and receive again until end of transmission */
while (recvMsgSize > 0){ /* zero indicates end of transmission */
/* Echo message back to client */
if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recvMsgSize)
DieWithError("send() failed");
/* See if there is more data to receive */
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
}
fclose(fp);
close(clntSocket); /* Close client socket */
}
HandleTCPclient received command from client like input.txt and check that file and send back to the client but i got segmentation fault(core dumped). here input.txt contain just one text file
enter code here
Your code is not using your supplied port, but it trying to connect to 7, you may not have a echo server running. Try changing to
in_port_t servPort = (argc ==4) ? atoi(argv[3]) : 7;