im making a simple TCP client-server in c and im trying to send a message from the client to the server, but im having some problems with it.
The server does send the message (integer value > 0) but the client is unable to receive it (integer value > 0)
here is the code:
Client
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
int main()
{
int s_id;
char *msg = "hello";
struct sockaddr_in serv_addr;
s_id = socket (AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (1156);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s_id,(struct sockaddr *) &serv_addr, sizeof (struct sockaddr));
int r = recv (s_id, (char *) msg, 9, 0);
printf("%d \n", r );
printf("%s \n", msg );
return 0;
}
Server:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main()
{
int s_id;
char *msg = "connected";
struct sockaddr_in my_addr, remote_addr;
s_id = socket (PF_INET,SOCK_STREAM,0);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(1156);
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(s_id,(struct sockaddr *) &my_addr, sizeof(struct sockaddr));
listen (s_id,5);
int size = sizeof (struct sockaddr_in);
int new_sd = accept (s_id, (struct sockaddr *) &remote_addr, &size);
int s= send(new_sd, (void *)msg, 9, 0);
printf("%d \n", s );
return 0;
}
The outputs i get (after first starting the server, and then the client) are
server side: 9
client-side: -1
hello
I am using Ubuntu 11.04 and the gcc compiler.
I hope someone out there can help.
Thank you
Umar
char *msg = "hello";
This is a string literal. It's a constant, and you can't change it.
int r = recv (s_id, (char *) msg, 9, 0);
And there you're trying to write to it.
Change your declaration to:
char msg[20];
memset(msg, 0, sizeof(msg));
If you make that change, your code works as expected.
In C you're going to have to allocate and manage buffers - there's no free lunch :)
Also take note of the other answer from Nikolai N Fetissov - you really should be checking return codes from all the system calls.
You never check for errors after any of the system calls. All of socket(2), connect(2), etc. return -1 on failure, then you can print the error description with, say, perror(3) function. Each system call manual page lists possible errors.
Edit 0:
The real problem is probably what Brian points out - you are trying to receive data into read-only memory on the client. Does it die with a segfault?
Related
I'm trying to learn UDP on C.
My goal is to send a message in console, in the client consol to the server, and sending the exact same message from the server to the client.
When I send a message from client to server, I do receive it, but the opposit is not working, and the waiting is infinite.
I don't have any problem in console.
The weird thing is that i'm using the exact same methode to send both messages.
Here's my client, Thanks to everyone helping me :)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define BUFSIZE 4096
// Driver code
int main(int argc, char *argv[]) {
char buffer[BUFSIZE];
struct sockaddr_in servaddr, cliaddr;
int len, n;
char *adresse= argv[1];
if (argc<1){
perror("nb args not enough");
exit(EXIT_FAILURE);
}
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(adresse);
servaddr.sin_port = htons(PORT);
// Socket()
int udp_server = socket(AF_INET, SOCK_DGRAM, 0) ;
if(udp_server<0){
perror("socket creation failed \n");
exit(EXIT_FAILURE);
}
// Bind())
int errBind = bind(udp_server, (const struct sockaddr *)&servaddr, sizeof(servaddr));
if(errBind<0){
perror("errBind \n" );
exit(EXIT_FAILURE);
}
// recvfrom()
n = recvfrom(udp_server, (char *)buffer, BUFSIZE,0, ( struct sockaddr *) &cliaddr,&len);
if (n<0){
perror("recvfrom error\n" );
exit(EXIT_FAILURE);
}
buffer[n] = '\0';
printf("CLIENT: %s\n", buffer);
char *message ="caca";
sendto(udp_server, (const char *)message, strlen(message),
0, (const struct sockaddr *) &cliaddr,
len);
close(udp_server);
//////////////////////////This part below is never reached
printf("end");
return 0;
}
Also here's my server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define BUFSIZE 4096
// Driver code
int main(int argc, char *argv[]) {
char buffer[BUFSIZE];
// char *message = "AAAAAAAAAAAAAAAAAA";
struct sockaddr_in servaddr, cliaddr;
int len, n;
char *adresse= argv[1];
if (argc<1){
perror("nombre d'arguments insuffisents, veuillez entrer :\n ./serveur port_serveur \n");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(adresse);
// servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Socket()
int udp_server = socket(AF_INET, SOCK_DGRAM, 0) ;
if(udp_server<0){
perror("socket creation failed \n");
exit(EXIT_FAILURE);
}
// Bind())
int errBind = bind(udp_server, (const struct sockaddr *)&servaddr, sizeof(servaddr));
if(errBind<0){
perror("errBind \n" );
exit(EXIT_FAILURE);
}
// recvfrom()
n = recvfrom(udp_server, (char *)buffer, BUFSIZE,0, ( struct sockaddr *) &cliaddr,&len);
if (n<0){
perror("recvfrom error\n" );
exit(EXIT_FAILURE);
}
buffer[n] = '\0';
printf("CLIENT: %s\n", buffer);
int l = sendto(udp_server, (const char *)buffer, strlen(buffer),
0, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
close(udp_server);
printf("end");
//////////////// This is reached
return 0;
}
There are several issues. The main issue is that both the client and server first tries to receive, then send. Thus they cannot both receive the message from the other party. Also, the client need not explicitly bind the socket.
In principle, the client must know the server address, but the server does not know the client address. Hence, the flow of communication must be that the client first sends a message to the server which will make the client known to the server. The server can then send a message to the address of the client.
In summary, the server should:
Create socket
Bind socket
Wait for message (recvfrom())
Send message to sender of the received message (sendto())
Close socket
The client should:
Create socket
Send message to the server (sendto())
Wait for message (recvfrom())
Close socket
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 am trying to make a client-server communication using UNIX sockets and using the STREAM protocol.
My server is running fine, but my client is not working. Whenever I try to send or receive data, I get an error : "socket operation on non-socket". I really don't see where it comes from, because my server is very similar and I don't have any problem. My server is on my local machine (127.0.0.1) and port 5000. It is open and listening (I checked with the netstat command).
The code is there :
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#define CHECK(ret, mes) if ((ret) == -1) {perror(mes); exit(-1);}
#define STRING_LENGTH 250
int createSocketINETClient(short mode, char *addr, short port)
{
int s;
struct sockaddr_in moi, server;
int moi_len, server_len;
moi.sin_family = AF_INET;
moi.sin_port = htons(port);
moi.sin_addr.s_addr = inet_addr(addr);
memset(moi.sin_zero, 0, 8);
s = socket(AF_INET, mode, 0);
CHECK(s, "socket");
moi_len = sizeof(moi);
CHECK(bind(s, (struct sockaddr*) &moi, moi_len), "bind");
return s;
}
void infoSocket (int s)
{
struct sockaddr_in sock_addr;
socklen_t len = sizeof(sock_addr);
getsockname(s, (struct sockaddr*) &sock_addr, &len);
printf("Onfo of socket %d\n", s);
printf("\t IP : %s\n", inet_ntoa(sock_addr.sin_addr));
printf("\t port : %d\n\n", ntohs(sock_addr.sin_port));
}
int main ()
{
int bytes;
int sock = createSocketINETClient(SOCK_STREAM, "0.0.0.0", 0);
struct sockaddr_in serveurSock;
int client = 0, clientSockLen = 0;
char message[] = "I am a message that is supposed to WORK !!!!\n";
char fromServer[STRING_LENGTH] = "";
infoSocket(sock);
serveurSock.sin_family = AF_INET;
serveurSock.sin_port = htons(5000);
serveurSock.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serveurSock.sin_zero, 0, 8);
CHECK(connect(sock, (struct sockaddr*) &serveurSock, sizeof(serveurSock)), "connect");
usleep(1000000);
CHECK((bytes = send(client, message, sizeof(message), 0)), "send");
printf("Message sent to server : %d bytes, \"%s\"\n", bytes, message);
CHECK((bytes = recv(client, fromServer, sizeof(fromServer), 0)), "recv");
printf("Message received from server : %d bytes, \"%s\"\n", bytes, fromServer);
close(client);
printf("Client released !\n\n");
return 0;
}
What did I do wrong ?
EDIT : The error comes from this line :
CHECK((bytes = send(client, message, sizeof(message), 0)), "send");
you are using the "client" variable as a socket parameter to sendto() when in fact you should use the "sock" variable.
should you strace the program, you could see the following:
connect(3, {sa_family=AF_INET, sin_port=htons(5000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
sendto(0, "I am a message that is supposed "..., 46, 0, NULL, 0) = -1 ENOTSOCK (Socket operation on non-socket)
note the first sendto() parameter which is 0 (by default this is the stdin file descriptor) when in fact it should be 3 (see connect(...) line)
as a side note, you don't need to bind() the client socket unless you have an explicit reason to do so (using some other route than the default one, bypassing a firewall rule somewhere, etc). the os will assign by default the ip of the network interface the default route goes through and a random free port.
In the posted code you initialize int client = 0 and then I don't see you change it. So when you call send(0, ...) you obviously get that error.
As already mentioned by #EJP in comment to your question it can be a typo because it looks like you really was intended to use sock (as you connected it: connect(sock, ...) instead of client in call to send.
I'm writing a basic Client/Server program in C, using UDP. The idea of the program is that the client sends a message to the server, the server receives it, then echoes it back to the client (the goal being to measure RTT for UDP). Unfortunately, on the server side, when the program attempts to call sendto() to echo the message, I receive the error "Can't assign requested address".
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#define SERVER_PORT 7000
#define MAX_PENDING 10
#define MAX_LINE 1024000
int main()
{
struct sockaddr_in sin, sout;
socklen_t soutLen;
char buf[MAX_LINE];
int len;
int msgLen;
int s;
char *msg;
if( (s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
perror("could not establish UDP socket");
exit(1);
}
/* build address data structure */
bzero((char *)& sin, sizeof( sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if( (bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0){
perror("udpServer: bind");
exit( 1);
}
while(1){
if((msgLen = recvfrom(s, buf, sizeof(buf), 0,(struct sockaddr *)&sout, &soutLen))<0){
perror("udpServer: recvfrom()");
exit( 1);
}
if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, sizeof(sout)))<0 ){
perror("udpServer: sendto()");
exit( 1);
}
free(msg);
}
}
Thanks in advance: I'm pretty new to C, so any advice is much appreciated!
The problem is that your sout you pass to sendto is not correct, because you are not correctly setting it's size when passing it to recvfrom:
man recvfrom:
ssize_t
recvfrom(int socket, void *restrict buffer, size_t length,
int flags, struct sockaddr *restrict address,
socklen_t *restrict address_len);
If address is not a null pointer and the socket is not connection-oriented, the source address of the message is filled in. The address_len argument is a
value-result argument, initialized to the size of the buffer associated with address, and modified on return to indicate the actual size of the address
stored there.
When you pass &sout to recvfrom, you also have to tell recvfrom the size of the structure you're passing in so it knows how much data it can write there -- soutLen is both an in parameter and an out parameter. Since you are not initializing soutLen, it probably has some value smaller than the actual size of the structure, which means that what you end up with in sout is not valid.
So you need to initialize soutLen:
struct sockaddr_in sin, sout;
socklen_t soutLen = sizeof(sout);
You should then pass this value as the size to sendto instead of sizeouf(sout) (this may not be required but it's good practice):
if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, soutLen))<0 ){
Also just as a note, you are freeing msg which you never allocated. This is unrelated but might cause problems later.
Hope this helps.
I am writing a simple program using sockets to receive actual date from server.
I am getting this error and i don't know where i am making a mistake.
Client:
/* Make the necessary includes and set up the variables. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main ()
{
int sockfd;
socklen_t len;
struct sockaddr_in address;
int result;
int id=2, answer, length;
char *s;
/* Create a socket for the client. */
sockfd = socket (AF_INET, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr ("127.0.0.1");
address.sin_port = htons (9734);
len = sizeof (address);
/* Now connect our socket to the server's socket. */
result = connect (sockfd, (struct sockaddr *) &address, len);
if (result == -1)
{
perror ("oops: netclient");
exit (1);
}
/* We can now read/write via sockfd. */
write(sockfd, &id, sizeof(id)); /* sending the request id */
read(sockfd, &answer, sizeof(answer)); /* receiving the answer id*/
if(answer==1002){
printf("Odebrano wlasciwa odpowiedz\n");
read(sockfd, &length, sizeof(length)); /* receiving the answer string length*/
s=(char*)malloc(length*sizeof(char)); /* receiving the string with the date */
read(sockfd, s, length);
printf ("Date from server = %s\n", s);
}
free(s);
close (sockfd);
exit (0);
}
Server:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
int main ()
{
int server_sockfd, client_sockfd;
int length;
char *s;
int id;
int answer=1002;
socklen_t server_len, client_len;
time_t rtime;
struct tm *timeinfo;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket (AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl (INADDR_ANY);
server_address.sin_port = htons (9734);
server_len = sizeof (server_address);
bind (server_sockfd, (struct sockaddr *) &server_address, server_len);
/* Create a connection queue and wait for clients. */
listen (server_sockfd, 5);
while (1)
{
printf ("server waiting\n");
/* Accept connection. */
client_len = sizeof (client_address);
client_sockfd = accept (server_sockfd,
(struct sockaddr *) &client_address,
&client_len);
/* We can now read/write to the client on client_sockfd.
The five second delay is just for this demonstration. */
read(client_sockfd, &id, sizeof(int)); /*receive request id */
if(id==2){
write(client_sockfd, &answer, sizeof(int)); /* sending an answer_id*/
time(&rtime);
timeinfo=localtime(&rtime);
s=(char*)malloc(sizeof(asctime(timeinfo))*sizeof(char));
printf("%s\n", asctime(timeinfo));
s=asctime(timeinfo);
printf("Size of s:%lx\n", sizeof(s));
length = htons(strlen(s));
write (client_sockfd, &length, sizeof(length)); /* sending the answer string length to the client */
printf("Date: %s\n", s);
write (client_sockfd, s, length); /* sending string with date to the server */
}
free(s);
close (client_sockfd);
}
}
I am almost certain that there is something wrong with allocing/freeing the space with the string containing actual date but i can't see the actual mistake.
EDIT:
Actually, i didn't know how to solve this problem in this mentioned way but i've came up with other idea.
I just send the result of asctime(timeinfo) over the server without using char* s.
So i don't write the date to char *s.
Program works fine now with no errors but i guess there is a way to do it some other way.
Well, even though, many thanks for the help, was helpful.
In your server, you overwrite s with asctime(...) after allocating it. This leaks the original memory. Also, the return value of asctime is a static buffer that cannot be freed.
Here's an excerpt from your code:
char *s;
if(answer==1002){
printf("Odebrano wlasciwa odpowiedz\n");
read(sockfd, &length, sizeof(length)); /* receiving the answer string length*/
s=(char*)malloc(length*sizeof(char)); /* receiving the string with the date */
printf ("Date from server = %s\n", s);
}
free(s);
Note what happens if 'answer' is not equal to 1002 -- you're calling free() on an uninitialized value. That is likely the cause of the error you are seeing. (This same mistake is present in both programs)
Refering the server code:
Here you allocate memory to s:
s=(char*)malloc(sizeof(asctime(timeinfo))*sizeof(char));
Here you overwrite the pointer with the value receive from asctime() so the original value returned by malloc() is lost introducing a memory leak:
s=asctime(timeinfo);
Here you then try to free what had been received from asctime(), which is a reference to static memory and gherefore cannot be freed.
free(s);