Related
I've got a simple client/server application. The user writes strings in the console. When he pushes enter string is sent. I can transfer one line correctly, but after it substitutes the first letter of first sent word to each next. For example, if a user sends "Hello", the server will get "Hello", but after, if I send "Hello" again, the server will get "HHello". If I try to clear buffer at the client-side after sending it, it never sends something again.
Server code:
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 57174
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
char buffer[1024];
bzero(buffer, sizeof(buffer));
int step = 0;
while(1){
valread = read( new_socket , buffer, 1024);
if(valread == 0)
break;
printf("%s", buffer );
printf("\n");
bzero(buffer, sizeof(buffer));
};
return 0;
}
Client code:
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 57174
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2]));
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
// char buffer[1024] = {0};
unsigned int N = 10, delta=10, i = 0;
char* buf = (char*) malloc (sizeof(char)*N);
while (1) {
buf[i] = getchar();
if(buf[i] == 27)
break;
if(buf[i] == 10){
send(sock , buf , strlen(buf) , 0 );
// bzero(buf, sizeof(buf));
N = 10;
buf = (char*) realloc (buf, sizeof(char)*N);
i = 0;
}
if (++i >= N) {
N += delta;
buf = (char*) realloc (buf, sizeof(char)*N);
}
}
return 0;
}
if a user sends "Hello", the server will get "Hello", but after, if I send "Hello" again, the server will get "HHello"
This is because you missed an else in your client, in
if(buf[i] == 10){
send(sock , buf , strlen(buf) , 0 );
// bzero(buf, sizeof(buf));
N = 10;
buf = (char*) realloc (buf, sizeof(char)*N);
i = 0;
}
if (++i >= N) {
N += delta;
buf = (char*) realloc (buf, sizeof(char)*N);
}
you need to replace
if (++i >= N) {
by
else if (++i >= N) {
else after you sent you buffer and set i to 0 you increment it, and you will memorize the next char at the index 1, the character at the index 0 is still present and you will send it again and again
You also have a problem in your client at
send(sock , buf , strlen(buf) , 0 );
because you do not put a null character in buff needed by strlen to return the expected value, so the behavior is undefined. In fact you do not need strlen, just do
send(sock , buf , i , 0 );
supposing you do not want to send the \n
On your server side
char buffer[1024];
...
valread = read( new_socket , buffer, 1024);
if(valread == 0)
break;
printf("%s", buffer );
you fill each time buffer with null characters but in case you read 1024 characters there is no null character in your buffer and printf will go out of the buffer with an undefined behavior
warning read returns -1 on error, valread == 0 is wrong
remove all your bzero an just do
char buffer[1024];
...
while ((valread = read(new_socket, buffer, sizeof(buffer)-1)) > 0) {
buffer[valread ] = 0;
printf("%s", buffer);
}
notice I used sizeof(buffer) rather than 1024, that allows to be sure to have the right size even you resize buffer
Other remarks for the client :
the variable hello is useless
by definition sizeof(char) values 1, so sizeof(char)*N can be replaced by N everywhere
do not compare the read char with the literal 10 and 27, compare with '\n' and '\e'
you do not manage the EOF in input, for that you need to save the read char in an int rather than a char (like buf[i] is) to compare it with EOF
In the server the variable step is useless
Out of that you use SOCK_STREAM so your socket is a stream (tcp not udp), that means you cannot suppose the size of the data you read each time you call read, I mean if the client sent N bytes that does not mean the server will read N bytes on the corresponding read (if I can say 'corresponding' because there is no correspondence ;-) ).
Supposing the other problems are fixed if you input azeqsd\n you send azeqsd but may be on the server side you will read azeq so print azeq\n and on the next loop you will read sd and print sd\n.
It is also possible the server read a partial or full concatenation of several buffers sent separably by the client.
Do you want that behavior ? if no you need to send the size before each buffer to know how much to read even on several times to constitute the full sent buffer (an other advantage is you no not read byte per
I'm wondering how to convert a char[] array to a char *
For example, in my code I am trying to access a web server using a hostname like "example.com"
Using my code, if I set a char * to "example.com" like below, it works perfectly.
char *host = "example.com";
But, what I really want to do is be able to read from a client program using a socket, write to a char[] array, and use the data obtained from that as the hostname.
For example,
char buffer[4096], hostname[4096];
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
wbhost = gethostbyname(hostname);
when my code gets to the last line, it just sits there, so I'm thinking its a typing problem, since when I do this:
char *host = "example.com";
...
wbhost = gethostbyname(host);
It works, and is able to get the data from the web and send it properly to my client program.
Any ideas are appreciated.
In the client program I use fgets() to read into a char[] from stdin then use write() to write to the socket for the server program to read. I had tried to use strcat() to add '\0' to the end of the char[] before writing to the socket but that didn't seem to do anything
Full Code: (Please ignore the comments, just trying different things for now)
client
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sockfd, portnum, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
if(argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
portnum = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("ERROR opening Socket");
exit(1);
}
server = gethostbyname(argv[1]);
if(sockfd == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(1);
}
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(portnum);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR, on connecting");
exit(1);
}
printf("Please enter the Host name: ");
bzero(buffer, 4096);
fgets(buffer, 4095, stdin);
//strcat(buffer, "\0");
n = write(sockfd, buffer, strlen(buffer));
if(n < 0)
{
printf("Error writing to socket");
exit(1);
}
bzero(buffer, 4096);
n = read(sockfd,buffer, 4095);
if(n < 0)
{
printf("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
server
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portnum, clilen;
char buffer[4096], hostname[4096];
pid_t p_id;
struct sockaddr_in serv_addr, cli_addr;
int n, pid, hostname_len;
//char *host;
char *host = "example.com";
if(argc < 2)
{
fprintf(stderr, "ERROR, NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);//socket is made
if(sockfd < 0)
{
fprintf(stderr, "ERROR opening socket!!");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portnum = atoi(argv[1]);//port num
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portnum);
if(bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
fprintf(stderr, "ERROR on binding");
exit(1);
}
if( listen(sockfd, 5) < 0)
{
printf("ERROR ON LISTEN");
exit(1);
}
// accept
clilen = sizeof(cli_addr);
do{
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if(newsockfd < 0)
{
fprintf(stderr, "ERROR on accept\n");
exit(1);
}
pid = fork();
if(pid == 0)
{
bzero(buffer, 4096);
n = read(newsockfd, buffer, 4095);
if(n < 0)
{//message from client
fprintf(stderr, "ERROR Reading from socket\n");
exit(1);
}
strcpy(hostname, buffer);
printf("Here is the hostname: %s\n", &hostname[0]);
//variables used for acsessing webserver?
int sockwb, wbport, x;
struct sockaddr_in webser_addr;
struct hostent *wbhost;
char webbuf[4096];//sending to webserver
wbport = 80;//port used to access web server
sockwb = socket(AF_INET, SOCK_STREAM, 0);
if(sockwb < 0)
{
printf("Error opeing websocket\n");
exit(1);
}
// hostname_len = sizeof(hostname) / sizeof(hostname[0]);
// printf("%d\n", hostname_len);
// memcpy(host, hostname, hostname_len);
// host[hostname_len] = '\0';
printf("%s\n", host);
// hostname[hostname_len] = '\0';
// host = &hostname[0];
//wbhost = gethostbyname(hostname);
wbhost = gethostbyname(host);
//printf("%s", wbhost->h_name);
printf("here2\n");
/*if(wbhost == NULL)
{
printf("NO SUCH web HOST\n");
exit(1);
}
*/
bzero((char*) &webser_addr, sizeof(webser_addr));
webser_addr.sin_family = AF_INET;
bcopy((char *)wbhost->h_addr, (char *)&webser_addr.sin_addr.s_addr, wbhost->h_length);
webser_addr.sin_port = htons(wbport);
// printf("here3\n");
if(connect(sockwb, (struct sockaddr *) &webser_addr,sizeof(webser_addr)) < 0)
{
printf("Error on web connecting\n");
exit(1);
}
bzero(webbuf, 4096);
strcpy(webbuf, "GET / HTTP/1.0\r\nHost: ");
// strcat(webbuf, hostname);
strcat(webbuf, host);
strcat(webbuf, "\r\nConnection: close\r\n\r\n");
// const char * request = "GET / HTTP/1.0\r\nHost: example.com\r\nConnection: close\r\n\r\n";
// printf("%s\n", request);
// x = write(sockwb, request, strlen(request));
printf("%s\n", webbuf);
x = write(sockwb, webbuf, strlen(webbuf));
if(x < 0)
{
printf("Error writing to web sock");
exit(1);
}
bzero(webbuf, 4096);
x = read(sockwb, webbuf, 4096);
if(n < 0)
{
printf("Error reading from web socket");
exit(1);
}
printf("%d\n", (int)strlen(webbuf));
printf("%s\n",webbuf);
n = write(newsockfd, webbuf, 4095 );//write back to client
if(n < 0)
{
fprintf(stderr, "ERROR WRITING to socket");
exit(1);
}
//printf("%s\n", webbuf);
}//end of if pid==0
printf("closing client");
close(newsockfd);//closing client socket
}while(1);
return 0;
}
The code you posted runs unimpeded. When you ask for help, you should always post a complete, verifiable example. Check that the code you post actually reproduces the problem!
Looking at what the code does, it seems that in the server, you meant to use the host name that you read as the argument to gethostbyname. You can do that with
host = &hostname[0];
or simpler
host = hostname;
or by not using two separate variables in the first place.
When you use an array in a context that expects a value (as opposed to e.g. taking its address or its sizeof), the array decays into a pointer to its first element. So here hostname is equivalent to hostname[0].
After that change, check the trace closely, or, to make the problem more visible, change the tracing line to
printf("[%s]\n", hostname);
You'll see
[aaa.com
]
The client reads a line with fgets, which includes the terminating newline character in its count. The client dutifully forwards the complete line to the server. And so the server looks up a host name containing a newline character, which doesn't exist. You don't check the return code of gethostbyname (you should!), it returns a null pointer, and the program crashes when it tries to read from it.
#Gilles is right, you have an '\n' at the end of the hostname, the following piece of code replaces the '\n' by 0 which is the equivalent of the character '\0':
extern int h_errno;
...
hostname[strlen(hostname) - 1] = 0;
wbhost = gethostbyname(hostname);
if (!wbhost) {
printf("Failed! %s\n", strerror(h_errno));
exit(1);
}
...
A char[] is an array of chars. A char* is a pointer to a char - generally (but not always) the start of a string.
If you want to get a pointer to the start of your array, you don't even need to do anything! This conversion happens implicitly:
char hello[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
// or: char hello[] = "hello"; (equivalent to above)
printf("%s", hello); // prints hello
puts(hello); // also prints hello
char *hello2 = hello;
puts(hello2); // also prints hello
Probably the easiest way to 'convert' char[] to char * is:
char example_array[] = "example";
char * example_pointer = (char *)calloc(1, strlen(example_array) + 1); // + 1 for the '\0' character
strcpy(example_pointer, example_array);
I have to write a TCP server program that holds an integer, that should be modifiable by the client programs. It should kind of resemble a bankaccount. Everything works fine, except one thing:
When a client first connects to the server, it will wait for a welcoming message (the server has to be iterative, so it should only handle one client at a time). The server always just sends the first couple of letters of the welcoming message. All other messages are transferred completely and correctly.
In line 49, the welcoming message is first copied to a char-array and then written to the socket. This is where the error is... Only the first 1-5 letters are sent (different each time a new client connects). In other places where I use sprintf() to copy a message to a char-array and then writing it to the socket, everything works just like I want it to.
I have also tried using snprintf(), but that doesn't work either. What am I doing wrong? :D
So this would be an example output on client side:
Connected!
Waiting for welcome message...
We
After that, I could start entering commands to the server. But the whole welcome message is cut of after two letters. But as said above, sometimes its just one letter, sometimes its five :D.
Anyway, here's my code (if there are any other errors or things I should avoid, feel free to tell me :D):
client:
#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>
#define BufferSize 99999
void error(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char msg[BufferSize], data[BufferSize];
if (argc < 3) error("usage: <hostname> <port>\n");
server = gethostbyname(argv[1]);
if (server == NULL) error("Host not found!");
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("socket() error");
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("connect() error");
printf("Connected!\nWaiting for welcome message...\n");
memset(msg, 0, BufferSize);
n = read(sockfd, msg, BufferSize - 1);
if (n < 0) error("read() error");
printf("%s\n", msg);
memset(data, 0, BufferSize);
while (fgets(data, BufferSize, stdin) != NULL) {
data[strlen(data) - 1] = '\0'; //remove trailing newline char
n = write(sockfd, data, strlen(data) + 1);
if (n < 0) error("write() error");
if (strcmp(data, "exit") == 0) break;
memset(msg, 0, BufferSize);
n = read(sockfd, msg, BufferSize - 1);
if (n < 0) error("read() error");
if (n==0) error("Server shut down...");
printf("%s\n", msg);
memset(data, 0, BufferSize);
}
close(sockfd);
return 0;
}
server:
#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 <limits.h>
#define BufferSize 99999
#define ClientWaiting 100
void error(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, n, amount, balance, balOld;
socklen_t clilen;
char msg[BufferSize], data[BufferSize], *splitBuf[2];
struct sockaddr_in serv_addr, cli_addr;
balance = 0;
if (argc < 2) error("usage: <port>");
portno = atoi(argv[1]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("socket() error");
memset(&serv_addr, 0, sizeof (serv_addr));
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("bind() error");
listen(sockfd, ClientWaiting);
while (1) {
printf("Waiting for new client...\n");
clilen = sizeof (cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("accept() error");
printf("New connection accepted...\n");
memset(data, 0, BufferSize);
sprintf(data, "Welcome!\nPlease use the following commands:\n<put, get> <positive integer>\nBalance: %d€", balance);
n = write(newsockfd, data, strlen(msg) + 1);
if (n < 0) error("write() error");
while (1) {
splitBuf[0] = NULL;
splitBuf[1] = NULL;
memset(data, 0, BufferSize);
memset(msg, 0, BufferSize);
n = read(newsockfd, msg, BufferSize - 1);
if (n < 0) {
fprintf(stderr, "read() error\n");
break;
}
if (n == 0) {
printf("Client disconnected...\n");
break;
}
printf("Message received: %s\n", msg);
if (strcmp(msg, "exit") == 0) break;
splitBuf[0] = strtok(msg, " ");
splitBuf[1] = strtok(NULL, " ");
if (splitBuf[1] == NULL) {
strcpy(data, "Please use the following commands:\n<put, get> <positive integer>");
} else {
amount = atoi(splitBuf[1]);
if (amount <= 0) {
strcpy(data, "Please use the following commands:\n<put, get> <positive integer>");
} else if (strcmp(splitBuf[0], "put") == 0) {
balOld = balance;
balance += amount;
if (balance < balOld) {
balance = INT_MAX;
sprintf(data, "Warning! Overflow!\nBalance: %d€", balance);
} else {
sprintf(data, "Balance: %d€", balance);
}
printf("New balance: %d€\n", balance);
} else if (strcmp(splitBuf[0], "get") == 0) {
balOld = balance;
balance -= amount;
if (balance > balOld) {
balance = INT_MIN;
sprintf(data, "Warning! Underflow!\nBalance: %d€", balance);
} else {
sprintf(data, "Balance: %d€", balance);
}
printf("New balance: %d€\n", balance);
}
}
n = write(newsockfd, data, strlen(data) + 1);
if (n < 0) error("write() error");
}
close(newsockfd);
}
close(newsockfd);
close(sockfd);
return 0;
}
This example is way too long for people on SO to debug. (We're not compilers and debuggers.)
Your first step must be decomposing the program into smaller, more easily understood pieces that can be debugged independently. There are a couple of ways of doing that:
adding checkpoints that test your assertions
breaking code into more easily understandable and independently testable functions
For example, I look at:
splitBuf[0] = strtok(msg, " ");
splitBuf[1] = strtok(NULL, " ");
Does splitBuf contain what you expect? (Is NULL a valid parameter to strtok?)
I recommend two things:
#include
# Are my assumptions met?
assert( splitBuf[0]!=null );
assert( splitBuf[1]!=null );
#ifdef DEBUG
printf("splitBuf[0]=%s\n", splitBuf[0]);
printf("splitBuf[1]=%s\n", splitBuf[1]);
#endif
Compile with -DDEBUG=1 to ensure that DEBUG is defined, or add:
#define DEBUG
at the top of the file.
Second, programming is much easier if you tackle smaller problems, then work on and test your answers to those problems independently. Let's say you need to parse a message from the network and extract a balance, then you might write:
int parseBalance(char const* serverMessage) {
...
return balance;
}
You can now write a test:
void tests()
{
// test parseBalance
assert( 100 == parseBalance("100") )
... more tests
}
Minimally, you could call tests() at the start of your program to perform a self-test (read up on "unit testing" for better approaches).
IF you program in this way:
often the problems will become more easily apparent
if you are stuck and post to SO, you only need to post the minimal function and test case.
I believe your problem is in your first read() call. You do a single read, expecting to get all of the welcome message. But that isn't how TCP works. TCP puts the stream data into packets according to its own internal rules, and the receiving system can make it available in any amount it wants.
You cannot rely on getting all of the data the server wrote in a single read.
In fact the server is messed up too. You cannot expect a write call to write everything you say. The operating system's send buffer for the socket might be full or it might have had a signal interrupt the call.
You need send and receive buffers and functions to handle a loop around read and write that continues until you receive a complete line or send a complete buffer.
i have implemented a program which takes input from client, performs operation on server and writes the data to the client. ls command is what i have chosen for example.
Now my doubt is,
1) what if the input is very huge in bytes??
2) what is the maximum data that can be sent through a socket port??
client.c
int main()
{
FILE *fp;
int servfd, clifd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
int cliaddr_len;
char str[4096], clientip[16];
int n;
servfd = socket(AF_INET, SOCK_STREAM, 0);
if(servfd < 0)
{
perror("socket");
exit(5);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
exit(0);
}
listen(servfd, 5);
printf("Server is waiting for client connection.....\n");
while(1)
{
cliaddr_len=sizeof(cliaddr);
clifd = accept(servfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
strcpy(clientip, inet_ntoa(cliaddr.sin_addr));
printf("Client connected: %s\n", clientip);
if(fork() == 0)
{
close(servfd);
while(1)
{
n = read(clifd, str, sizeof(str));
str[n] = 0;
if(strcmp(str, "end") == 0)
{
printf("\nclient(%s) is ending session and server is waiting for new connections\n\n", clientip);
break;
}
else if (strcmp(str, "ls") == 0) {
system("ls >> temp.txt");
fp = fopen("temp.txt", "r");
fread(str, 1, 500, fp);
remove("temp.txt");
}
else
printf("Received from client(%s): %s\n", clientip, str);
write(clifd, str, strlen(str));
}
close(clifd);
exit(0);
}
else
{
close(clifd);
}
}
}
server.c
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char str[500];
int n;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("Could not connect to server: %s\n", strerror(errno));
exit(1);
}
while(1)
{
printf("Enter message: ");
scanf(" %[^\n]", str);
write(sockfd, str, strlen(str));
if(strcmp(str, "end") == 0)
break;
n = read(sockfd, str, sizeof(str));
str[n] = 0;
printf("Read from server: %s\n", str);
}
close(sockfd);
}
As for your question no 1. the huge data is broken in many packets & then sent packet by packet its done by OS internally. & the one packet size depends on your system OS(you can change it.It is called MTU maximum transfer unit).
& for your question no 2. the data send by a socket port may be infinite coz as long as u wish to send data it will send. there is no limit.!!!
Q: What if the input is very huge in bytes?? What is the maximum data that can be sent through a socket port??
A: There is no limit on the size of a TCP/IP stream. In theory, you could send and receive an infinite number of bytes.
... HOWEVER ...
1) The receiver must never assume is will ever get all the bytes at once, in a single read. You must always read socket data in a loop, reading as much at a time as you wish, and appending it to the data you've already read.
2) You can send a "large" amount of data at once, but the OS will buffer it behind your back.
3) Even then, there's an OS limit. For example, here the maximum send buffer size is 1 048 576 bytes.:
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_send.html
If you need to send more, you must send() in a loop.
PS:
As Anish recommended, definitely check out Beej's Guide to Network programming:
http://beej.us/guide/bgnet/output/html/multipage/
I have a program that creates a socket (server and client program) and sends a message via a TCP port using that socket. My question is, how can I exchange multiple messages?
Every time I send a message the port gets closed and I need to use another port to send another message.
For example, I have to send 2 numbers from the client to the server and the server needs to reply back the total sum of the numbers I send. How would I achieve sending undefined number or even 2 numbers over the SAME port?
Here are the codes (pretty much standard stuff):
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
char* Itoa(int value, char* str, int radix)
{
static char dig[] =
"0123456789"
"abcdefghijklmnopqrstuvwxyz";
int n = 0, neg = 0;
unsigned int v;
char* p, *q;
char c;
if (radix == 10 && value < 0) {
value = -value;
neg = 1;
}
v = value;
do {
str[n++] = dig[v%radix];
v /= radix;
} while (v);
if (neg)
str[n++] = '-';
str[n] = '\0';
for (p = str, q = p + (n-1); p < q; ++p, --q)
c = *p, *p = *q, *q = c;
return str;
}
void error (const char *msg)
{
perror (msg);
exit (1);
}
int main (int argc, char *argv[])
{
if (argc < 2)
{
fprintf (stderr, "ERROR, no port provided\n");
exit (1);
}
//nova varijabla za sumiranje primljenih brojeva
int suma=0;
int sockfd, newsockfd, portno,i;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
for (i=0;i<2;i++)
{
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error ("ERROR opening socket");
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
portno = atoi (argv[1]);
portno+=i;
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");
//test za ispis otvorenog porta
printf("Uspjesno otvoren localhost na portu %d\n", portno);
listen (sockfd, 5);
clilen = sizeof (cli_addr);
newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error ("ERROR on accept");
memset (buffer, 0, 256);
n = read (newsockfd, buffer, 255);
if (n < 0) error ("ERROR reading from socket");
printf ("%d. proslan broj: %s\n", i+1, buffer);
//print
suma=suma+atoi(buffer);
//radi!! printf("suma je %d\n", suma);
//od klijenta: n = write (sockfd, buffer, strlen (buffer));
//char * itoa ( int value, char * str, int base );
Itoa(suma, buffer, 10);
n = write (newsockfd, buffer, strlen(buffer));
if (n < 0) error ("ERROR writing to socket");
close (newsockfd);
close (sockfd);
}
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error (const char *msg)
{
perror (msg);
exit (1);
}
int
main (int argc, char *argv[])
{
if (argc < 3)
{
fprintf (stderr, "usage %s hostname port\n", argv[0]);
exit (1);
}
int sockfd, portno, n,i;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
for (i=0;i<2;i++)
{
portno = atoi (argv[2]);
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error ("Ne mogu otvoriti socket!");
server = gethostbyname (argv[1]);
if (server == NULL)
{
fprintf (stderr, "Greska, ne postoji!\n");
exit (1);
}
memset ((char *) &serv_addr, 0, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy ((char *) server->h_addr,
(char *) &serv_addr.sin_addr.s_addr,
server->h_length);
portno+=i;
serv_addr.sin_port = htons (portno);
if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error ("ERROR connecting");
printf ("%d. broj za slanje: ", i+1);
memset (buffer, 0, 256);
fgets (buffer, 255, stdin);
n = write (sockfd, buffer, strlen (buffer));
if (n < 0)
error ("ERROR writing to socket");
memset (buffer, 0, 256);
n = read (sockfd, buffer, 255);
if (n < 0)
error ("ERROR reading from socket");
if (i==1) printf ("Suma iznosi: %s\n", buffer);
close (sockfd);
}
return 0;
}
So, for example, I run the code and get this for the server side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./server2 5000
Uspjesno otvoren localhost na portu 5000
1. proslan broj: 45
Uspjesno otvoren localhost na portu 5001
2. proslan broj: 56
j#PC ~/Desktop/Mreze/Lab1/rijeseno $
And on the client side:
j#PC ~/Desktop/Mreze/Lab1/rijeseno $ ./client2 localhost 5000
1. broj za slanje: 45
2. broj za slanje: 56
Suma iznosi: 101
I've tried putting a while loop so it loops the part with sending but without success. Please explain to me where should I even put it so it works. Thank you!
Here is a problem:
n = read (newsockfd, buffer, 255);
What you do, is you perform read once, and the data might not be fully available. The fact is, you need to read data, as long as you received the data completely, or detected EOF condition (-1 return value).
Generally you need to write more reliable code for receiving part, as it is not guaranteed on stream protocol that your message boundaries are kept in any form.
Here is a (very unoptimal, yet simple) code for reading data:
int readLine(int fd, char data[])
{
size_t len = 0;
while (len < maxlen)
{
char c;
int ret = read(fd, &c, 1);
if (ret < 0)
{
data[len] = 0;
return len; // EOF reached
}
if (c == '\n')
{
data[len] = 0;
return len; // EOF reached
}
data[len++] = c;
}
}
And usage example:
char buffer[256];
int num1, num2;
readLine(newsockfd, buffer);
num1 = atoi(buffer);
readLine(newsockfd, buffer);
num2 = atoi(buffer);
First Put your connection() function before and close() after for loop. Just for an idea
connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)
for (i=0;i<n;i++){
// do you introspection with server
// actually send number to server
}
// Code to read result: SUM from server
close (sockfd);