ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
As topic, I want writing a client and server program that server would receive connection from client and respond appropriate message to client. What i already is client would send whatever message including number string to the server and the server will send back to client of what exactly it receive. With the sequence above, I want to create 1 more feature, which is when the client send a string of integer number, for example: 1234567 to the server. The server will automatically compute this string of number and send back the compute answer to the client. Lets say i want the answer to be display like this:
- Client: 1234567
- Server compute and send to client
Client display : 28
Client display: 10
Client display : 1
The first answer, which is 28 is adding the intergers 1+2+3+4+5+6+7 = 28
The second will be 2+8 = 10
The third will be 1+0 = 1
When the numbers reach a single digit,for example like : 1 from the above, the server will stop sending answer and wait for next message to receive.
Is there any idea of calculating the string of numbers in that way?
Kindly attach some code example if necessary, thank you
Here's my code
Code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#define MAXLINE 4096 /*max text line length*/
#define SERV_PORT 3000 /*port*/
#define LISTENQ 8 /*maximum number of client connections */
int main (int argc, char **argv)
{
int listenfd, connfd, n;
pid_t childpid;
socklen_t clilen;
char buf[MAXLINE];
struct sockaddr_in cliaddr, servaddr;
//creation of the socket
listenfd = socket (AF_INET, SOCK_STREAM, 0);
//preparation of the socket address
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen (listenfd, LISTENQ);
printf("%s\n","Server running...waiting for connections.");
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = accept (listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("%s\n","Received request...");
while ( (n = recv(connfd, buf, MAXLINE,0)) > 0) {
printf("%s","String received from and resent to the client:");
puts(buf);
send(connfd, buf, n, 0);
}
if (n < 0) {
perror("Read error");
exit(1);
}
close(connfd);
}
//close listening socket
close (listenfd);
}
Code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#define MAXLINE 4096 /*max text line length*/
#define SERV_PORT 3000 /*port*/
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXLINE], recvline[MAXLINE];
//basic check of the arguments
//additional checks can be inserted
if (argc !=2) {
perror("Usage: TCPClient <IP address of the server");
exit(1);
}
//Create a socket for the client
//If sockfd<0 there was an error in the creation of the socket
if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <0) {
perror("Problem in creating the socket");
exit(2);
}
//Creation of the socket
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr= inet_addr(argv[1]);
servaddr.sin_port = htons(SERV_PORT); //convert to big-endian order
//Connection of the client to the socket
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0) {
perror("Problem in connecting to the server");
exit(3);
}
while (fgets(sendline, MAXLINE, stdin) != NULL) {
send(sockfd, sendline, strlen(sendline), 0);
if (recv(sockfd, recvline, MAXLINE,0) == 0){
//error: server terminated prematurely
perror("The server terminated prematurely");
exit(4);
}
printf("%s", "String received from the server: ");
fputs(recvline, stdout);
}
exit(0);
}
There are lots of people interested in TCP/IP client-server programming, but your intent seems strange. Strange enough to look like homework, so many will just skip the thread after the first few lines.
Here is a bit of server code. While it works, it is quite badly designed -- intentionally so; while it works, it is not the way I'd personally do it. I hope that this will give you a small boost in your own efforts.
Code:
#define _BSD_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define PORT 3000
#define BACKLOG 8
unsigned int sum_digits_in(const void *const data, const size_t length)
{
const char *const string = (const char *const)data;
size_t index = length;
unsigned int result = 0U;
while (index-->0)
if (string[index] >= '0' && string[index] <= '9')
result += string[index] - '0';
return result;
}
unsigned int sum_digits(const unsigned int value)
{
unsigned int digits = value;
unsigned int result = 0U;
while (digits) {
result += digits % 10U;
digits /= 10U;
}
if (result == value)
return 0U;
return result;
}
int main()
{
int socketfd, descriptor;
struct sockaddr_in remote, local;
socklen_t remote_len;
char request[4096];
char response[1024]; /* Actually ~ 30 max. used */
char client[1024];
unsigned int value;
int size, n, i;
ssize_t bytes;
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
fprintf(stderr, "Cannot create socket: %s.\n", strerror(errno));
return 1;
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(PORT);
if (bind(socketfd, (struct sockaddr *)&local, (socklen_t)sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Cannot bind to port %d: %s.\n", PORT, strerror(errno));
return 1;
}
if (listen(socketfd, BACKLOG) == -1) {
fprintf(stderr, "Cannot listen: %s.\n", strerror(errno));
return 1;
}
while (1) {
remote_len = sizeof(struct sockaddr_in);
descriptor = accept(socketfd, (struct sockaddr *)&remote, &remote_len);
if (descriptor == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
fprintf(stderr, "Error in an incoming connection: %s.\n", strerror(errno));
return 1;
}
if (!inet_ntop(AF_INET, &remote.sin_addr, client, sizeof(client) - 1)) {
client[0] = '?';
client[1] = 0;
}
more:
bytes = read(descriptor, request, sizeof(request));
if (bytes == (ssize_t)0) {
fprintf(stderr, "%s: Disconnected, bye bye!\n", client);
fflush(stderr);
close(descriptor);
continue;
}
if (bytes < (ssize_t)0) {
const char *const errmsg = (bytes == (ssize_t)-1) ? strerror(errno) : "Disconnected";
fprintf(stderr, "%s: %s.\n", client, errmsg);
fflush(stderr);
close(descriptor);
continue;
}
fprintf(stderr, "%s: %d bytes requested.\n", client, (int)bytes);
fflush(stderr);
value = sum_digits_in(request, (size_t)bytes);
if (!value) {
fprintf(stderr, "%s: No data. Bye bye!\n", client);
fflush(stderr);
close(descriptor);
continue;
}
size = 0;
do {
n = snprintf(response + size, sizeof(response) - 1 - size, "%u\n", value);
if (n < 1) {
/* Should never happen. */
size = 0;
break;
}
size += n;
value = sum_digits(value);
} while (value);
fprintf(stderr, "%s: Sending '", client);
for (i = 0; i < size; i++)
fputc( (response[i]>='0' && response[i]<='9') ? response[i] : ' ', stderr);
fprintf(stderr, "' (%d bytes).\n", size);
fflush(stderr);
/* Send the response string. */
if (size > 0) {
const char *p = response;
const char *const q = response + size;
while (p < q) {
bytes = write(descriptor, p, (size_t)(q - p));
if (bytes > (ssize_t)0)
p += bytes;
else
if (bytes != -1 || errno != EINTR)
break;
}
n = (int)(p - response);
} else
n = 0;
/* Everything OK to continue? */
if (n == size && size > 0)
goto more;
fprintf(stderr, "%s: Sent only %d of %d bytes. Closing connection.\n", client, n, size);
fflush(stderr);
close(descriptor);
}
/* Never reached. */
close(socketfd);
return 127;
}
The program will bind to the wildcard address, port 3000, so it will accept connections on any IP address the machine owns. You can use for example telnet as the client.
If you save the above as digit-server.c you can compile and run it using
Then, in another terminal on the same machine, run
Code:
telnet 127.0.0.1 3000
Telnet will send each completed line, so type some numbers (the server will ignore everything except digits), and press enter to send the line to the server. The server will close the connection if you supply an empty line (anything without any digits in it). You can of course also close telnet or the terminal you're running telnet in; the server will detect and handle that too. (I don't think it notices if a remote machine crashes suddenly while communicating; I think it stays waiting for input for a long time.)
You could write a client for the above service, too, although just about any TCP/IP-based client works. Here is a command-line client written in Bash:
Code:
#!/bin/bash
[ -n "$SERVER" ] || SERVER=127.0.0.1
[ -n "$PORT" ] || PORT=3000
if [ $# -gt 0 ]; then
while [ $# -gt 0 ]; do
echo "$1 = "
exec 3<>/dev/tcp/$SERVER/$PORT
echo "$1" >&3
shift 1
while read -t 0.1 LINE <&3 ; do
echo " $LINE"
done
exec 3<&-
done
else
echo 'Enter an empty line to quit.' >&2
while read -p '? ' INPUT ; do
[ -n "$INPUT" ] || exit 0
exec 3<>/dev/tcp/$SERVER/$PORT
echo "$INPUT" >&3
while read -t 0.1 LINE <&3 ; do
echo " $LINE"
done
exec 3<&-
done
fi
Last edited by Nominal Animal; 09-11-2011 at 09:43 AM.
Reason: Added compiling and running instructions, and a Bash client.
it's not a homework, it was a program that i created before but I wish to modify after one of my friend has inspired of his program which could compute the price of product when the client send the product ID to server.
Back to topic, the code you gave me is a server side, but how about the client side? or is a standalone program? Also may I know how to run your program? You did not explain clearly of executing it, whether is with ip or port. Sorry for disturbance
Back to topic, the code you gave me is a server side, but how about the client side?
I added an example Bash client. You can run that either by specifying the numbers on the command line, or by interactively typing.
Something like this is usually written on top of HTTP. If you format the messages in XML, you can interface to it in a lot of different ways; for example, you can write a bit of Javascript on a web page, and access it from that script (interactively, no need to reload anything). Or you can format the message in say Python or PHP, do a query using the HTTP facilities available in those languages, and parse the XML message. A protocol similar to
is extremely easy to handle in different languages and environments, and you can even extend the format while maintaining backwards compatibility, if you design it carefully. To do stuff like this, learn CGI, FastCGI, WSGI to do it directly on top of a good HTTP server (Apache, nginx, LigHTTPD, for example), or use one of the frameworks. For this level of things, maintainability, adaptability, ease of development, reliability and so on are much more important than lower-level implementation details.
Dropping down to the socket level is really only warranted if there is an actual reason. Of course, learning stuff is a very good reason. As is doing stuff just for fun. But your questions have straddled two totally different areas -- simple services, and hard-core low-level socket I/O --, which is a bit jarring. There is nothing wrong in either, it is just that not many are used to working with them at the same time. (I suspect this is the primary reason others have not chipped in.)
I suggest you might find it better worth your time to split these areas for now, and develop them separately. Client-server exercises are much more fun with higher level languages. (I am talking about mental exercises, not homework, by the way.) Designing and trying out different ways to communicate -- and seeing the results immediately in your browser is much more rewarding in the short term.
On the socket level, you may find that transferring binary data (properly formatted) is actually easier in C than all the stringy stuff. Plain C does not have much in the way of string handling, so most of the examples I've seen just skip the important bits (error handling, dynamic memory management, and so on), and do "something" with sockets to show how it is "in principle" done. Having two programs talk to each other without any human intervention is also a good idea; humans just make things more difficult anyway. Experiment!
I suggest you first write a program that has the desired behavior using standard input and output to simulate interacting with a client. After that it's trivial to make it work over a socket, and setting up the socket is largely independent of the task itself. You really have two problems to solve:
Create a line-based program that will read lines of digits. For each line it will perform an uncertain number of operations, writing one line per operation. The finality of the last operation is predictable (i.e. both ends know that 1 digit means "done").
Create a client/server pair that communicate one line at a time via a socket.
Both of these can and should be developed separately. In fact, it wouldn't be uncommon in the second program above to fork when a new connection is made, replace standard input and output of the child with the socket, then execvp the first program. This is essentially the task inetd performs.
Kevin Barry
On the socket level, you may find that transferring binary data (properly formatted) is actually easier in C than all the stringy stuff.
One problem with switching to binary is you can't use any FILE* functions like fgets. That means if you're reading delimited input where the data segments aren't of predictable length you have to implement your own buffering system to compensate for reading more than is needed. The other alternative is to read a character at a time. With proper binary data, e.g. C-structs, you can run into problems with width, alignment, and endianness. In my experience, you might as well use C++ or flex/bison if you're dealing with text from read, and binary data needs some sort of protocol (or file format) design.
Kevin Barry
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.