I have the following code for client and server
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int socket_fd;
struct sockaddr_in dest;
struct hostent *hostptr;
struct { char head; u_long body; char tail; } msgbuf;
socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
bzero((char *) &dest, sizeof(dest)); /* They say you must do this */
hostptr = gethostbyname(argv[1]);
dest.sin_family = (short) AF_INET;
bcopy(hostptr->h_addr, (char *)&dest.sin_addr,hostptr->h_length);
dest.sin_port = htons((u_short)0x3333);
msgbuf.head = '<';
msgbuf.body = htonl(getpid()); /* IMPORTANT! */
msgbuf.tail = '>';
sendto(socket_fd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr *)&dest,
sizeof(dest));
return 0;
}
server:
#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int socket_fd, cc, fsize;
struct sockaddr_in s_in, from;
struct { char head; u_long body; char tail;} msg;
socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
bzero((char *) &s_in, sizeof(s_in)); /* They say you must do this */
s_in.sin_family = (short)AF_INET;
s_in.sin_addr.s_addr = htonl(INADDR_ANY); /* WILDCARD */
s_in.sin_port = htons((u_short)0x3333);
printsin( &s_in, "RECV_UDP", "Local socket is:");
fflush(stdout);
bind(socket_fd, (struct sockaddr *)&s_in, sizeof(s_in));
for(;;) {
fsize = sizeof(from);
cc = recvfrom(socket_fd,&msg,sizeof(msg),0,(struct sockaddr *)&from,&fsize);
//printsin( &from, "recv_udp: ", "Packet from:");
printf("Got data ::%c%ld%c\n",msg.head,(long) ntohl(msg.body),msg.tail);
fflush(stdout);
}
return 0;
}
I'm looking for a way to change this code so that:
1.The client will send my name to the server and then will receive the server response.
2.On the server side, the server will receive the client name (instead of the current msg structure) and will send back its name.
I'm assuming I should just put my name in the msgbuf.body like this
msgbuf.head = '<';
msgbuf.body = 'liana';
msgbuf.tail = '>';
and delete the
msgbuf.body = htonl(getpid()); line.
or maybe make a new string for my name like this string name="liana";
and put it in the msgbuf.body like this msgbuf.body=name;(???)
is this the right deriction?
for reciving the response of the server I assume it is the same way as it was done for the server
should I add to client something like this?
int socket_fd, cc, fsize; // the socket that we receive to
struct sockaddr_in s_in, from; // decleration of the server and sending
(to the server) struct
fflush(stdout);//to ensure that whatever you just wrote to a file/the console is indeed written out on disk/the console.
bind(socket_fd, (struct sockaddr *)&s_in, sizeof(s_in));// conecting
between
the socket and all the details we entered
for(;;) {//infinite loop
fsize = sizeof(from);//set the size of the socket we resive to
cc = recvfrom(socket_fd,&msg,sizeof(msg),0,(struct sockaddr
*)&from,&fsize);//recive massage using UDP protocol
printf("Got data ::%c%ld%c\n",msg.head,(long) ntohl(msg.body),msg.tail);
//print the whole massage
fflush(stdout);//to ensure that whatever you just wrote to a file/the
console is indeed written out on disk/the console.
}
and just leave it like this without changing anything?
**how can I make the server receive the my name (instead of the current msg
structure)and send it back?
should I send it back using the
sendto(socket_fd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr *)&dest,
sizeof(dest));
line?
**if I cant use the structure anymore how should i change this line?****
any help whould be appreciated,I'm kind of new to C and never worked with the client/server model
Related
I wrote a server program and a client program that communicate with sockets on linux ubuntu. The client program outputs Received: 艎��
This my server code:
/*** tcp_server.c ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main() {
int sock_fd, new_fd, bytes;
struct sockaddr_in seraddr, cliaddr;
char data[1024];
socklen_t cli_addr_size;
cli_addr_size = sizeof(cliaddr);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY : It received Network Interface that connected server defined interface, htonl :
seraddr.sin_port = htons(5050);
bind(sock_fd, (struct sockaddr *)&seraddr, sizeof(seraddr));
listen(sock_fd, 10);
while (1) {
new_fd = accept(sock_fd, (struct sockaddr *)&cliaddr, &cli_addr_size);
bytes = recv(new_fd, data, 1024, 0);
send(new_fd, data, bytes, 0);
close(new_fd);
}
close(sock_fd);
}
My client code is:
/*** tcp_client.c ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(int argc, char *argv[]) {
int sock_fd, bytes;
struct sockaddr_in ser_addr;
char *snddata, rcvdata[1024];
snddata = argv[2];
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
memset(&ser_addr, 0,sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = inet_addr(argv[1]); // INADDR_ANY : It received Network Interface that connected server defined interface, htonl :
ser_addr.sin_port = htons(5050);
connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
send(sock_fd, snddata, strlen(snddata), 0);
printf("Received: ");
bytes = recv(sock_fd, rcvdata, 1024, 0);
rcvdata[bytes] = '\0';
printf("%s\n", rcvdata);
close(sock_fd);
}
First I got an error for argument 3 of accept, then I changed
new_fd = accept(sock_fd, (struct sockaddr *)&cliaddr, sizeof(cliaddr);
But It still produces this strange word.
Try to change your send() and receive() functions so that you have full control over how much and which byte you send from the buffer (data[1024]) like in this thread : C socket: recv and send all data and also see Beej's Guide to Network Programming (http://beej.us/guide/bgnet/)
Also make sure that you initialize your data buffers:
data[1024] = "";
rcvdata[1024] = "";
or
data[1024];
data[0] = '\0';
rcvdata[1024];
rcvdata[0] = '\0';
, background is in this thread : Why I am getting this unusually symbols by printing char string
i've done a simple client/server program where the server wait for an external connection and return the connection-socket if the port number of the client is in the range of [1025-2048] otherwise return -1. The problem is that when i get the port number by the client adress (which should be stored in the sockaddr structure) it says me that the client port number is zero, but in the client program i've set the client portnumber to 1999.
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int function(int fd_socket) {
int fd_socket_acc;
int len;
int port;
struct sockaddr_in client_addr;
puts("WAITING FOR CLIENT...");
fd_socket_acc = accept(fd_socket, (struct sockaddr*)&client_addr, &len);
puts("CONNECTION DONE.");
port = ntohs (client_addr.sin_port);
printf("client port number: %d \n", port);
if (port >= 1024 && port <= 2048) {
close (fd_socket_acc);
return fd_socket_acc;
}
else {
close(fd_socket_acc);
return -1;
}
}
int main(int argc, char *argv[]) {
int fd_socket;
struct sockaddr_in local_addr;
fd_socket = socket(AF_INET, SOCK_STREAM, 0);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(1887);
local_addr.sin_addr.s_addr = INADDR_ANY;
bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));
listen(fd_socket, 3);
function(fd_socket);
//close(fd_socket);
}
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int main(int argc, char *argv[]) {
int fd_socket;
struct sockaddr_in local_addr;
struct sockaddr_in server_addr;
struct hostent *hp;
fd_socket = socket(AF_INET, SOCK_STREAM, 0);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(1999);
local_addr.sin_addr.s_addr = INADDR_ANY;
bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1887);
//hostname is "ubuntu"
hp = gethostbyname("ubuntu");
bcopy(hp->h_addr, &server_addr.sin_addr, 4);
printf("%d \n", ntohs(local_addr.sin_port));
connect(fd_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
wait(2);
close(fd_socket);
}
If i get the port number in client with a printf("%d", ntohs(local_addr.sin_port)) it stamps correctly 1999, but if i get the port number of client in server with printf("%d", ntohs(client_addr.sin_port)) it stamps 0. Why?
thanks in advance!
In order to obtain the client port number in client_addr through accept you have to tell accept how big that buffer is by setting
socklen_t len = sizeof(client_addr);
You can alternatively retrieve it by calling afterwards
len = sizeof(client_addr);
getpeername(fd_socket_acc, (struct sockaddr*)&client_addr, &len);
Maybe because you do not set the variable len to anything, and I suspect that your compiler sets it to 0.
What happens is that you try to accept with an undefined len size.
Adding len=sizeof( struct sockaddr_in ); before making a call to accept would help to fill the passed client_addr correctly.
Problem:
I need some help with an error in my code. The chat client works when I only have one client running but if i use more clients. Only the last client messages will show up on my server. my client.c seems to work since it is sending but for some reason recv() is not getting the previous client send().
How code works:
I set up my server and spawn a new thread whenever a new client connects. the thread will handle the messages i get form the client and print it on the server screen.
Code:
CLIENT.C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char ** argv){
//get port
//int port = atoi(argv[1]);
int server_port = atoi(argv[1]);
char * name =argv[2];
int namelength = strlen(name);
//set up server adress and socket
int sock = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(server_port);
//connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("connect failed");
exit(1);
}
//set up client name
char * buff = malloc(5000*sizeof(char));
//get the chatting
//char * other_message = malloc(5000*sizeof(char));
while(1){
printf("ENTER MESSAGE:\n");
char message[5000];
strcpy(message, name);
strcat(message,": ");
printf("%s", message);
scanf("%[^\n]",buff);
getchar();
strcat(message,buff);
int sent = send(sock , message , strlen(message) , MSG_DONTWAIT );
if (sent == -1)
perror("Send error: ");
else
printf("Sent bytes: %d\n", sent);
}
return 0;
}
SERVER.C
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
pthread_t * threads = NULL;
int * client_fd = NULL;
int num_clients;
int thread_num;
void * client_handler(void * cl)
{
int * client = (int *)cl;
char * message = malloc(5000*sizeof(char));
printf("Connected: %d\n",*client);
int byte=1;
//recieve the message from clients
while(1)
{
byte=recv(*client, message , 5000 , 0);
if(byte< 0)
break;
//send message to all other clients
printf("%s\n",message);
printf("Recieved bytes:%d\n",byte);
memset(message, 0, 5000);
/*for(i=0;i<num_clients;i++)
if(client_fd[i]!=*client)
send(*client , message , strlen(message),0);*/
}
printf("finished: %d\n",*client);
return NULL;
}
int main(int argc, char ** argv)
{
//get the port
int port = atoi(argv[1]);
//set up socket
int socket_fd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in server,client;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
//bind
if(bind(socket_fd, (struct sockaddr*)&server,sizeof(server)) < 0 ){
perror("binding error\n");
exit(1);
}
//listen
if( listen(socket_fd, 10) <0){
perror("binding error\n");
exit(1);
}
//accept incoming connectionns
threads = malloc(10*sizeof(pthread_t));
client_fd = malloc(10*sizeof(int));
int i=0;
int c = sizeof(struct sockaddr_in);
while(1)
{
int c_fd = accept(socket_fd,(struct sockaddr *)&client, (socklen_t*)&c);
if(c_fd < 0)
printf("error");
client_fd[i]=c_fd;
pthread_create(&threads[i],NULL,client_handler,(void *)(&c_fd));
i++;
num_clients=i;
}
return 0;
}
Sending C-style strings with strlen(). Does not send the terminating null. Use strlen()+1
Ignoring the value returned by recv(). TCP is a streaming protocol that only transfers bytes/octets. It does not transfer anything more complex. recv() may return one byte of your chat line, all of your chat line, or anything in between. To transfer any message more complex than one byte, you need a protocol and you must handle it. Yours is 'chat lines are null-terminated strings', so you need to call recv() in a loop and, using the returned value, concatenate the bytes received until the null arrives.
Trying to printf non-strings with "%s". You must not attempt to print out the received data until you are sure that a null has been received.
I am working on a server/client program for a project, for it to be able to work properly I need to use fopen and fprintf on the client. The server is going to take realtime data output from a USB joystick (the axis rotations) and send that information via TCP to the client which in turn writes that information to a file. I have followed THIS tutorial to get the TCP setup and its working perfectly. I am able to send messages from the server to the client. How can I take a command such as fprintf(fp, "2=%d\n", zAxis) from the server and send it to the client to be wrote to a file? Maybe I am overlooking something simple to accomplish this. I don't know where to begin, if I can send the zAxis variable from the server to the client I think I can figure it out from there.
Here is my code
SERVER.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORTNUM 2343
int main(int argc, char *argv[])
{
char msg1[10];
printf("Please enter info\n");
fgets(msg1, 20, stdin);
struct sockaddr_in dest; /* socket info about the machine connecting to us */
struct sockaddr_in serv; /* socket info about our server */
int mysocket; /* socket used to listen for incoming connections */
socklen_t socksize = sizeof(struct sockaddr_in);
memset(&serv, 0, sizeof(serv)); /* zero the struct before filling the fields */
serv.sin_family = AF_INET; /* set the type of connection to TCP/IP */
serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set our address to any interface */
serv.sin_port = htons(PORTNUM); /* set the server port number */
mysocket = socket(AF_INET, SOCK_STREAM, 0);
/* bind serv information to mysocket */
bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
/* start listening, allowing a queue of up to 1 pending connection */
listen(mysocket, 1);
int consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
while(consocket)
{
printf("Incoming connection from %s - sending welcome\n", inet_ntoa(dest.sin_addr));
send(consocket, msg1, strlen(msg1), 0);
consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
}
close(consocket);
close(mysocket);
return EXIT_SUCCESS;
}`
CLIENT.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXRCVLEN 500
#define PORTNUM 2343
int main(int argc, char *argv[])
{
char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
int len, mysocket;
struct sockaddr_in dest;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&dest, 0, sizeof(dest)); /* zero the struct */
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("192.168.254.16"); /* set destination IP number */
dest.sin_port = htons(PORTNUM); /* set destination port number */
connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr));
len = recv(mysocket, buffer, MAXRCVLEN, 0);
/* We have to null terminate the received data ourselves */
buffer[len] = '\0';
printf("Received %s (%d bytes).\n", buffer, len);
close(mysocket);
return EXIT_SUCCESS;
}
I am learning the Sockets networking API. In this process, I have written a simple Echo server that uses TCP. I wrote the code in such a way that, as long as the server is running, anything typed on the client's console should be echoed back to it. However, I am unable to achieve this. Although, for the first input, I get the echo, from next time onwards, I do not get any message.
I know, we can implement it to run for many clients using fork(), but I want to know the reason behind the blocking of the client, and if possible ways to correct it.
Here is the code for the client:
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#define MAXCOUNT 1024
int main(int argc, char* argv[])
{
int sfd;
char msg[MAXCOUNT];
char blanmsg[MAXCOUNT];
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
sfd = socket(AF_INET,SOCK_STREAM,0);
saddr.sin_family = AF_INET;
inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);
saddr.sin_port = htons(5004);
connect(sfd,(struct sockaddr*) &saddr, sizeof(saddr));
for(; ;) {
memset(msg,0,MAXCOUNT);
memset(blanmsg,0,MAXCOUNT);
fgets(msg,MAXCOUNT,stdin);
send(sfd,msg,strlen(msg),0);
recv(sfd,blanmsg,sizeof(blanmsg),0);
printf("%s",blanmsg);
fflush(stdout);
}
exit(0);
}
Here is the code for the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define MAXCOUNT 1024
int main(int argc, char* argv[])
{
int sfd,nsfd,n,i,cn;
char buf[MAXCOUNT];
socklen_t caddrlen;
struct sockaddr_in caddr,saddr; //Structs for Client and server Address in the Internet
sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr,0,sizeof(saddr)); //Clear the Server address structure
saddr.sin_family = AF_INET; //Internet Address Family
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_port = htons(5004);
bind(sfd, (struct sockaddr*) &saddr,sizeof(saddr));
listen(sfd,1);
for(; ;) {
caddrlen = sizeof(caddr);
nsfd = accept(sfd,(struct sockaddr*) &caddr,&caddrlen);
cn = recv(nsfd,buf,sizeof(buf),0);
if(cn == 0) {
exit(0);
}
buf[cn] = '\0';
send(nsfd,buf,strlen(buf),0);
}
close(nsfd);
exit(0);
}
You shouldn't call accept within the loop on the server. Move the accept before the for loop on the server and it should work how you expect.
Calling accept in the loop like that will make the server block until a new connection comes in. Your client is only opening a single connection, so the server will block on the second call to accept.
Your code is doing precisely what you asked it to do. You told it to accept a connection, receive some data from that connection, send that data back to the connection, then accept another connection. That's what it's doing. I suspect you want to move the accept call outside the for loop.
I think you required a code which servers multiple clients as well as echo message to respective clients.
so just have a look to your code again and note down modification
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define MAXCOUNT 1024
int main(int argc, char* argv[])
{
int sfd,nsfd,n,i,cn;
char buf[MAXCOUNT];
socklen_t caddrlen;
struct sockaddr_in caddr,saddr;
//Structs for Client and server Address in the Internet
sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr,0,sizeof(saddr)); //Clear the Server address structure
saddr.sin_family = AF_INET; //Internet Address Family
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_port = htons(5004);
bind(sfd, (struct sockaddr*) &saddr,sizeof(saddr));
listen(sfd,5);/*request queue size*/
while(1)
{//main loop for cuncorent server
caddrlen = sizeof(caddr);
nsfd = accept(sfd,(struct sockaddr*) &caddr,&caddrlen);
if(fork()==0)
{//only child code for serving a particular client
for(; ;) {//loop for reading and writing back msg cotineously
cn = recv(nsfd,buf,sizeof(buf),0);
if(cn == 0) {
exit(0);
}
buf[cn] = '\0';
send(nsfd,buf,strlen(buf),0);
}//serving loop ends
close(nsfd);
exit(0);
}//child code ends
}//main while loop ends
exit(0);
}