I have a problem with the implementation of a client/server chat.
The problem is that I can not handle the connection with two (or more) clients at the same time. In fact the server responds only to one client and not to all.
The server code is more less like this:
/*include*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
/*define*/
#define PORT 5050
#define MSG_SIZE 100
#define NUM_UTENTI 5
//the thread function
void *fun_receiver(void *);
void *sender2(void *);
/*////////////////////// MAIN FUNCTION /////////////////////////////*/
int main(){
int serverfd , clientfd, c, *new_client;
struct sockaddr_in server_addr , client_addr;
//Create socket
serverfd = socket(AF_INET , SOCK_STREAM , 0);
//Prepare the sockaddr_in structure
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons( PORT );
//Bind
bind(serverfd,(struct sockaddr *)&server_addr , sizeof(server_addr));
puts("bind done");
//Listen
listen(serverfd , 5);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//thread_id
int t=0;
pthread_t thread_receiver;
pthread_t thread_invio;
while(true){
clientfd = accept(serverfd, (struct sockaddr *)&client_addr, (socklen_t*)&c);
if (clientfd < 0){
perror("accept failed");
return 1;}
new_client=malloc(sizeof(int));
*new_client=clientfd;
if( pthread_create( &thread_receiver , NULL , fun_receiver , (void*) new_client) < 0){
perror("could not create thread");
return 1;
}
if( pthread_create( &thread_invio , NULL , sender2 , (void*) new_client) < 0){
perror("could not create thread");
return 1;
}
}//end while
close(serverfd);
return 0;
} //fine main
//////sender
void *sender2(void *clientfd)
{
int sock = *(int*)clientfd;
char buf[30];
while(true){
bzero(&buf, 30 * sizeof(char));
printf("Inserisci Messaggio3: ");
gets(buf);
int len, byte_sent;
len=strlen(buf);
byte_sent = send(sock, buf, len, 0);
}
return 0;
}
////receiver
void *fun_receivervoid *serverfd)
{
int sock = *(int*)serverfd;
char msg[MSG_SIZE];
bzero(&msg, MSG_SIZE * sizeof(char));
int read_size;
int count = 0;
while( (read_size=recv(sock, msg, MSG_SIZE * sizeof(char), 0)) > 0 ){
/*if(strcmp(msg, exit)==0){
printf("Arrivederci!\n");
close(sock);
}*/
printf("%s\n", msg);
bzero(&msg, MSG_SIZE * sizeof(char));
}
return 0;
}
the same code is in the client side after the connect(): there are two threads one for sending messages (to the server) and one for receiving messages (from the server). Both threads relies on the same client socket.
What happens:
The client1 connects to the server (writes and receives messages to/from the server) / / all ok!
The client2 connects to the server (writes messages to the server but doesn't receive anything..)
The problem is that if the server writes a message only client1 receives while client2 doesn't.
How is this possible? where I am wrong? I would like that server could send messages to all the clients not only one!
Your code can be improved in many ways. But I feel currently the critical problem here is in the
*new_client=clientfd;
The pointer (new_client) is not even initialized. And more over you want to use the value stored, in multiple threads.
In that case you need to have different memory areas, so that individual threads get the correct value of connection descriptor.
I would suggest to write
new_client = malloc(sizeof(int));
*new_client=clientfd;
Now individual threads will get the correct connection descriptor. I hope this will solve the problem.
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'm working on a multithreaded server/client. The problem I have is that the server handling sometimes looks a little bit various. The message, which is send back is always correct, but the message the server prints out is a little bit weird. If it is a short word like "hello" everything works. If it is a long word or there are spaces in the string like "Binominalkoeffizient" the out-printed serversided message is:
Binomina
lkoeffiz
ient
fiz
Any idea where my mistake is?
PS: The server reaction is the same when I use telnet!
Server-Main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include "server.h"
int main(int argc, const char * argv[]) {
int sock;
struct sockaddr_in server;
sock = socket(AF_INET, SOCK_STREAM, 0);
socketStatusCheck(sock);
puts("[*] Starting Server ...");
puts("[*] Initialize Server ...");
initializeServer(&server, 8888);
bindServerToAddress(sock, server);
puts("[*] Waiting for incomming connections ... ");
puts("");
listen(sock, 3);
connectionSwitch(sock);
close(sock);
return 0;
}
Server-File
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include "server.h"
void socketStatusCheck(int sock) {
if (sock == -1) {
perror("Error creating the socket: ");
exit(0);
}
}
void initializeServer(struct sockaddr_in *server, int port) {
server->sin_family = AF_INET;
server->sin_addr.s_addr = INADDR_ANY;
server->sin_port = htons(port);
}
void bindServerToAddress(int sock, struct sockaddr_in server) {
if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) {
perror("Error binding port: ");
}
}
void connectionSwitch(int sock) {
int nsock, lenbuf;
struct sockaddr_in client;
pthread_t pid = NULL;
lenbuf = sizeof(struct sockaddr_in);
while ((nsock = accept(sock, (struct sockaddr*) &client, (socklen_t*) &lenbuf))) {
puts("Client connected!");
if (pthread_create(&pid, NULL, connectionHandler, (void*) &nsock))
perror("Error creating thread: ");
}
if (nsock < 0) {
perror("Error accepting incomming client: ");
}
pthread_exit(pid);
}
void *connectionHandler(void *sockptr) {
int sock = *(int*) sockptr;
long isConnected;
char *smessage, *recvmessage;
smessage = "Hello! I am the server you just connected! \n";
write(sock, smessage, strlen(smessage));
recvmessage = malloc(5000 * sizeof(char)); // while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0)
while ((isConnected = recv(sock, recvmessage, sizeof(recvmessage), 0)) > 0) {
//write(sock, recvmessage, sizeof(recvmessage));
send(sock, recvmessage, sizeof(recvmessage), 0);
puts(recvmessage);
}
if (isConnected == 0) {
perror("Client disconnected: ");
fflush(stdout);
}
free(recvmessage); recvmessage = NULL;
return 0;
}
This really has nothing to do with multithreading, and everything to do with the nature of SOCK_STREAM sockets.
Stream sockets are, as the name suggests, a stream of bytes; they do not preserve message boundaries such that what is sent with one call to send is received with one call to recv. A single send may be broken up across multiple recv calls, or multiple send calls may be coalesced into a single recv, or both. They do guarantee order, in that the bytes will be received in the same order they are sent.
You'll need to implement your own record marking, perhaps by inserting \0 characters to delimit words, or by using length prefixes.
This is normal behavior. When you use send you don't know how many bytes will be sent. It may happen that all the words , characters are sent.However there are ways to solve this problem. One way is to write a simple header to the string you send , which contains the length of the string you are sending . So you know when the string is ending . For example you can use a thread to look continuously for messages and because the header contains the length of the string you know when to print a \n.The behavior of the send cannot be altered , because it is the Kernel , that is doing this .
In addition to what the other answers say already:
Your code specifically asks to read 8 bytes at a time. recvmessage is a pointer, and pointers are 8 bytes on your system, so sizeof(recvmessage) is 8.
I have just started learning basic networking concepts.I am trying to implement a multithread server-client prog in C.but the problem is instead of running multiple windows/terminals/instances for clients,i should use fork() to create children of client.so by creating children of client multiple clients will be created.now each of these child clients will communicate with the server on a thread.
Earlier i created a similar prog but in that for multiple client you have to open multiple windows for clients and run all of them.
I am having trouble where to modify my code (both in server and client ones.I think server one is ok.but i am having no idea where to fork() in client program and what changes should be made).
Actually i don't want to open multiple windows to run multiple client,thats why i am using fork() to create multiple copies of it.Is there any other way by which i can create multiple clients and connect them to my server prog via threads.
Server :
// socket server example, handles multiple clients using threads
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3000 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
c=sizeof(struct sockaddr_in);
while(client_sock=accept(socket_desc,(struct sockaddr*)&client,(socklen_t*)&c))
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
This will handle connection for each client
*/
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int n;
char sendBuff[100], client_message[2000];
while((n=recv(sock,client_message,2000,0))>0)
{
send(sock,client_message,n,0);
}
close(sock);
if(n==0)
{
puts("Client Disconnected");
}
else
{
perror("recv failed");
}
return 0;
}
Client:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SIZE 50
int main()
{
int sock_desc;
struct sockaddr_in serv_addr;
char sbuff[MAX_SIZE],rbuff[MAX_SIZE];
if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Failed creating socket\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(3000);
if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
printf("Failed to connect to server\n");
return -1;
}
printf("Connected successfully - Please enter string\n");
while(fgets(sbuff, MAX_SIZE , stdin)!=NULL)
{
send(sock_desc,sbuff,strlen(sbuff),0);
if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);//to clean buffer-->IMP otherwise previous word characters also came
}
close(sock_desc);
return 0;
}
You can create multiple clients using thread. Create a separate thread for each client and then from thread handler connect to the server. I am not sure if it is a good way or not.
Code:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SIZE 50
#define NUM_CLIENT 5
void *connection_handler(void *socket_desc);
int main()
{
int socket_desc , new_socket , c , *new_sock, i;
pthread_t sniffer_thread;
for (i=1; i<=NUM_CLIENT; i++) {
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) i) < 0)
{
perror("could not create thread");
return 1;
}
sleep(3);
}
pthread_exit(NULL);
return 0;
}
void *connection_handler(void *threadid)
{
int threadnum = (int)threadid;
int sock_desc;
struct sockaddr_in serv_addr;
char sbuff[MAX_SIZE],rbuff[MAX_SIZE];
if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Failed creating socket\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
printf("Failed to connect to server\n");
}
printf("Connected successfully client:%d\n", threadnum);
while(1)
{
printf("For thread : %d\n", threadnum);
fgets(sbuff, MAX_SIZE , stdin);
send(sock_desc,sbuff,strlen(sbuff),0);
if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);
sleep(2);
}
close(sock_desc);
return 0;
}
For understanding purpose, i used sleep.
REF:
http://www.amazon.com/UNIX-Network-Programming-Richard-Stevens/dp/0139498761
http://beej.us/guide/bgnet/
https://computing.llnl.gov/tutorials/pthreads/
Firstly, if you fork(), you will be creating additional processes, not additional threads. To create additional threads, you want to use pthread_create.
Secondly, as you are a student, the canonical answer here is 'read Stephens'. Not only is this an invaluable tool even for those of us experienced in writing socket I/O routines, but also it contains examples of non-threaded non-forking async I/O, and various ways to add threads and forking to them. I believe the one you want is: http://www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321637739 (chapter 14 if memory serves). This should be in your college library.
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 trying to make a program with a server and multiple clients can connect to that server through the predefined port nummber. By the way, this is TCP in C. I have the following server code below:
SERVER CODE:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int listenfd , connfd , c , *new_sock;
struct sockaddr_in servaddr , cliaddr;
listenfd = socket(PF_INET , SOCK_STREAM , 0);
if (listenfd == -1)
puts("SOCKET CREATION ERROR!");
puts("Socket created");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(54321);
bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr) );
listen(listenfd,2);;
c = sizeof(struct sockaddr_in);
while( (connfd = accept(listenfd, (struct sockaddr *)&cliaddr, (socklen_t*)&c)) ){
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = connfd;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("Thread Error Connection");
return 1;
}
puts("Handler assigned");
}
if (connfd < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *connection_handler(void *socket_desc)
{
int sock = *(int*)socket_desc;
int read_size;
char client_message[51]="";
while( (read_size = recv(sock , client_message , 50, 0)) > 0 )
{
printf("%s",client_message);
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
free(socket_desc);
return 0;
}
CLIENT CODE:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
socklen_t len = sizeof(servaddr);
char mesg[1024];
if(argc!=2){
printf("Usage: %s <ip_addr>\n",argv[0]);
exit(1);
}
sockfd = socket(PF_INET,SOCK_STREAM,0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(54321);
inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
while(1){
fgets(mesg,sizeof(mesg),stdin);
sendto(sockfd,mesg,strlen(mesg),0,(const struct sockaddr *)&servaddr,len);
}
close(sockfd);
return 0;
}
I get the following output:
Socket created
Connection accepted
Handler assigned
Hello There!
What could be the problem?
I don't know?
the problem?
Hey!
't know?
the problem?
I typed in the following strings in the client terminal:
Hello There!
What could be the problem?
I don't know?
Hey!
The problem is when I typed the third string, the output is the third string with some parts of the second string still appearing. What could be the problem? Thanks!
TCP is stream oriented.
You can not expect that write() writes as much data as you told it to write, as well as you can not expect that read() reads as much data as you told it ro read.
This both put together means that to transfer N bytes via a socket the number of calls to read() does not necessarily needs to match the number of calls to write().
And following this conclusion the only thing the reader could know is how much it read from the moment on it was created.
The only two synchronisation points between reader and writer are the creation and the shutdown of the connection. The period one can call a session.
So if one wants to transfer multiple blocks of data having different sizes unknown to the reader during one session one is in the need to establish additional synchronisation points during the session, that make the read detect that a full block had been received.
Doing so is implementing some sort of protocol.
There are endless possiblities how the protcol could look like. The detailed design of the protocol depends on the use cases which shall be covered by the application.
Assuming only text data shall be transfered a simple protocol could be to terminate each data block by a \n.
The writer loops around write() until all data is sent and finally sends a \n.
The reader loops around read() until a \n had been received.
C strings are null terminated. You're not sending the zero byte that would terminate your string in your recieving buffer, so your printf will print out all characters it find until it reaches some zero byte. strlen returns length of string in number of characters, but without counting the zero byte at the end.
Try to change line in your client:
sendto(sockfd,mesg,strlen(mesg),0,(const struct sockaddr *)&servaddr,len);
Into:
sendto(sockfd,mesg,1+strlen(mesg),0,(const struct sockaddr *)&servaddr,len);