This is the client side where it prompts user to enter a string and send it to the server
//send
printf("\nPlaintext : ");
gets(send_data);
send(sock,send_data,strlen(send_data), 0);
//recv
bytes_recieved = recv(sock, recv_data, 1024, 0);
recv_data[bytes_recieved] = '\0';
printf("\nEnciphered text = %s " , recv_data);
fflush(stdout);
close(sock);
And this is the server side.
sin_size = sizeof(struct sockaddr_in);
//accept
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
printf("\n I got a connection from (%s , %d)", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
//recv
bytes_recieved = recv(connected, recv_data, 1024,0);
recv_data[bytes_recieved] = '\0';
printf("\n RECIEVED DATA = %s " , recv_data);
cod = encipher(recv_data, key, 1); //printf("Code: %s\n", cod);
dec = encipher(cod, key, 0); //printf("Back: %s\n", dec);
//send
send(connected, cod, strlen(cod), 0);
send(connected, dec, strlen(dec), 0);
So the thing is, I want to send two strings named 'plaintext' and 'key' from the client. At the server side, I expected it to receive the two strings and process it under encipher() function and then send it back to the client.
How do I send two strings from a client and receive two strings from the server?
I would send the string first then get the server to write back some confirmation to the client that it received it. Then the client can send the key, the server can do what it needs to and return the message to the client. If you keep the socket connection open you can continue to send and receive information from/to either end of the connection with send() and recv(). There are a number of ways depending on the structure of your strings. You could use a delimiter in the data you send to the server to indicate the end of the string, so that the portion that remains is your key - this would allow the server to receive the data in one packet and reply in one packet. I am not sure there is a right way to do it - you must decide based on the needs of your application. Either way, you should check the return values of the socket functions to check that you are getting and sending what you think you are.
send a 16bit short containing the size of the 1st string, then the 1st string, then another short containing the size of the 2nd string then the 2nd string. On the server, read a 16bit int then read that many bytes, then do the same for the 2nd string.
Related
i am trying to implement 1 "Server" (broker) and 2 "Clients" in C with UDP Sockets. But i cant get it to work.
What is my Goal:
One of the clients (CLIENT A) can send a word to the Server and the server saves that word in a char[]. After that, everytime if the other Client (CLIENT B) sends a message to the server, and the word of Client A is contained in that message, the whole message will be sent to CLIENT A. If the word isnt in the message, nothing will happen.
The Implementation of the server without multiple Client A´s is no problem. But i cant get it to work with multiple Client A´s.
Lets face the problem:
The Server is listening with a select() to potential Client A and Client B.
if client B is sending a keyword, the code is doing the following:
if(FD_ISSET(server_cli, &server_fd)){
client_length = sizeof(client_addr);
bzero(buffer, sizeof(buffer));
nbytes = recvfrom(server_cli, buffer, sizeof(buffer), 0, (struct sockaddr *) &client_addr, &client_length);
memcpy(&save_ip[counter].client_address, &client_addr, sizeof(client_addr));
strcpy(save_ip[counter].topic, buffer);
fprintf(stderr, "\n[+] Subrequest from: %s - Topic: %s", inet_ntoa(save_ip[counter].client_address.sin_addr), save_ip[counter].topic);
counter = counter + 1;
}
save_ip[counter].client_address is a struct in an array (dont know how that is called - i am relatively new to C). Everytime a Client is sending a keyword, the counter is counter + 1 and the client- socket information from the struct i get from recvfrom() will be saved in there (that is the plan and that is working..)
if Client A is sending a message and the message contains the keyword of any of Client B´s it will do something like that:
else if( !strcmp( pub_topic, save_ip[temp_counter].topic )){
client_addr = save_ip[counter].client_address;
fprintf(stderr, "\nIP: %s", inet_ntoa(client_addr.sin_addr));
nbytes = sendto(server_cli, buffer, sizeof(buffer), 0, (struct sockaddr *) &save_ip[counter].client_address, sizeof(save_ip[counter].client_address));
fprintf(stderr, "\n\t[+] Sent Message to %s (User-Topic: %s)", inet_ntoa(save_ip[temp_counter].client_address.sin_addr), save_ip[temp_counter].topic);
So, as you can see... I am trying to save the sockaddr structs from clients in this:
struct clients {
struct sockaddr_in client_address;
int client_length_long;
char topic[512];
};
But that doesnt work at all. I can get IP Addresses and everything else from the struct (and the values are correct), but i cant integrate them in a sendto(). Nothing is received by Client B.
Is there any other/better solution? (Mine is not a solution - it doesnt work at all). Can you guys advice me something to get it to work?
So I made a simple server-client program that can communicate with each other using fifo file (msgfifo).
My question is: When I type a message which includes a space, the receiver process runs several times with number of words.
That's not I expected, as I expected to print it out as a whole sentence, but it doesn't, and I want to know why.
When I type a something to send, process send SIGUSR1 signal to another.
/* receive msg part */
/* added this using sigset(SIGUSR1, receiveSIGUSR1) */
void receiveSIGUSR1()
{
char* msg = "\nIncoming Message from client...";
char* msg2 = "\nClient : ";
char buf[max_of_msg];
int fd;
write(1, msg, strlen(msg)+1);
fflush(stdin);
if( (fd = open("./msgpipe", O_RDONLY)) < 0)
{ perror("open"); exit(1); }
read(fd, buf, max_of_msg);
close(fd);
write(1, msg2, strlen(msg2)+1);
write(1, buf, strlen(buf)+1);
flag = 0;
}
/*send msg part*/
while(1)
{
flag = -1;
printf("\nType what u want to send : ");
scanf(" %s", msg);
if(flag == 0) continue;
printf("msgtaken\n");
fflush(stdin);
if( (fd = open("./msgpipe", O_RDWR)) < 0)
{ perror("exit"); exit(1); }
kill(clpid, 30);
sleep(2);
printf("Send message to Client..\n");
write(fd, msg, max_of_msg);
printf("Message Sent...\n");
}
Expected:
Client : Hello Server this is client
Actual:
/* server */
Incoming Message from client... Hello Incoming Message
from client... this Incoming Message from client... is
Incoming Message from client... client Type what u
want to send :
/client/
Type what u want to send : Hello Server This is client
msgtaken Send message to server.. Message sent
Type what u want to send : msgtaken Send message to server..
Message sent Type what u want to send : msgtaken Send
message to server.. Message sent Type what u want to send
: msgtaken Send message to server.. Message sent Type
what u want to send : msgtaken Send message to server..
Message sent
Type what u want to send :
That's because this is how it takes input:
scanf(" %s", msg);
Let's have a look at the documentation of scanf (emphasis mine):
s: Any number of non-whitespace characters, stopping at the first
whitespace character found. A terminating null character is
automatically added at the end of the stored sequence.
That's why it stops after Hello when you send Hello Server this is client. Also note the space in " %s", this means that it will also ignore any whitespace at the start of the input. So when it reads the Server on the next run through the loop, this makes it ignore the space between Hello and Server. As a result, it goes through the loop five times, and the messages each time are Hello, Server, this, is and client.
Instead, you could use getline:
char *message = NULL;
size_t length;
getline(&message, &length, stdin);
// use message
free(message);
A little side note: to make your scanf call more safe, you can specify a maximum size for the string input:
scanf(" %99s", msg);
Per example, this would mean that only 99 char can be read in, plus a null terminator, for a buffer size of 100. This way you can avoid undefined behavior that would occur if the user would enter a string that is too big for your buffer.
I'm trying to implement a client-server application with multiclients using threads. Just to try, I would like to print the messages from each client, but when I send messages from a client, the server does not print anything.
Server (thread code)
void comunicationHandler(void *socket)
{
int sock = *(int*) socket;
char msg[2000];
while ((strcmp(msg, "!quit")) != 0) {
if (recv(sock, msg, 2000, 0) < 0)
puts("Error recv");
printf("%s", msg);
}
puts("Client Disconnected\n");
}
when I send "!quit", the Server goes in a infinite loop printing the messages
Client
for(;;) {
printf("\nInserisci il msg: ");
scanf("%s", msg);
if (strcmp(msg, "!quit") == 0)
break;
write(sd, msg, 2000);
}
There are multiple problems with your code:
TCP is stream based, there is no guarantee that all the bytes you send will be received in one shot on the other side. You need to modify code to check what is the number of bytes received and is it atleast equal to the size of "!quit" before you go in for the "strcmp" comparison.
Better to null terminate the buffer once you receive the buffer equal to the size of "!quit"
It is not clear as to why you are sending a 2000 bytes buffer from the client when you intend to send only "!quit". Modify and send only appropriate size as needed
Check recv return value against 0 also
Break out of the loop in both server and client once the Job is done.
Server goes in a infinite loop
You want to test recv()'s result against 0 and quit in this case. 0 indicates that the client orderly closed the connection.
I have been working on how to transfer an image using UDP in C, I have created a code that sometimes works, sometimes it doesn't. In what I think the issue is that sometimes the server receives more packages than writes. I know that I am trying to create the TCP, but that is what I am kind looking for, but not sure how to do it.
I think to fix it the client should send the buff of the img and only sends the second part when the server reply back to the client.
Here is the code:
Client:
while (!feof(p))
{
fread(*&c, 1, BLEN, p);
sprintf(buf, "%s", *&c);
temp=sendto(s,buf,BLEN, 0, (struct sockaddr *) &si_other, slen);
//sleep(3);
//printf("%d ",temp);
if(temp < 0)
{
fprintf(stderr,"sendto error.\n");
printf("erro");
exit(1);
}
i++;
}
Server:
while(1){
if(recvfrom(s, buf, BLEN, 0, (struct sockaddr *) &si_other, (unsigned int *) &slen)==-1){
perror("recvfrom error.\n");
exit(1);
}
//printf("%s ", &si_other);
flagr[0] = buf[0];
flagr[1] = buf[1];
flagr[2] = buf[2];
if (strcmp(flagr, flag) == 0 ){
break;
}
fwrite(buf, 1, BLEN, pp);
i++;
}
UDP is a datagram protocol, meaning that each call to sendto sends one message. If that message is larger than an IP packet can hold, it will be fragmented across multiple IP datagrams. If any one of those fragments fails to arrive, the whole thing is dropped at the OS level.
The data needs to be sent in chunks of no more than about 1450 bytes. Then the receiving side will need to read each packet and, because UDP does not guarantee that data will arrive in order, you will need to reassemble them in the proper order.
That means each packet has to have a user-defined header which contains the sequence number so that the receiver knows what order to put them in.
You also need to worry about retransmissions, since UDP doesn't guarantee that a packet that is send is actually received.
There's a program I wrote called UFTP which does all of this. Take a look at the documentation and code to get an idea of what you need to do to implement reliable data transfer over UDP.
Currently implementing a TCP socket in C. Using libcurl I am sending a HTTP POST request with some XML files. The connection and transmission is working correctly.
Now, when I try to send 2 different XML files in the same session to the server I always get the value of the first transmission I sent. Meaning I always get the old value, the socket does not give back the new value received on the socket.
Wireshark shows me that the different XML files are transmitted. Do I need to clean the socket somehow after each TCP connection has been made?
Here is my server implementation:
while (1) {
char buf[512];
connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
if (connfd == -1) {
perror("accept");
continue;
}
int rec;
rec = recv(connfd, buf, sizeof (buf), 0);
printf ("Receive val: %d\n", rec);
//DO STUFF
//Send back ACK
strcpy(sendBuff, "Received");
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
you close the session right after the first packet is received. This is why you don't get the next packet.
You should handle each incoming connection in a separate thread, or make sure somehow before you close the socket, that no more incoming data should arrive