String with thread in tcp client / server in C - c

I'm trying to develop an application in C to receive a message and send it in TCP. For that, I'm using a 2 threads : the server thread to listen and a client thread to send it.
Here the server and the main function :
void dostuff(int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
else {
pthread_t t_tcp_client;
pthread_create(&t_tcp_client, NULL, tcp_client, buffer);
}
n = write(sock,"Message received",18);
if (n < 0) error("ERROR writing to socket");
}
static void *tcp_server(void *p_data)
{
int sockfd, newsockfd, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
pid = fork();
if (pid < 0) error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
} else {
close(newsockfd);
}
}
close(sockfd);
return 0;
}
int main (void)
{
pthread_t t_tcp_server;
pthread_create(&t_tcp_server, NULL, tcp_server, NULL);
pthread_join(t_tcp_server, NULL);
return 0;
}
And the client thread :
static void *tcp_client(void *p_data)
{
if (p_data != NULL)
{
char const *message = p_data;
printf("Message transmitted : %s\n", message);
}
return 0;
}
The problem is that the client thread doesn't receive the good char, the result is :
Message transmitted : ???~?
I think the problem comes from the line : n = read(sock,buffer,255); but I don't really understand why.
Thank you for your help

static char buffer[256];
void dostuff(int sock)
{
int n;
bzero(buffer,256);
n = read(sock,buffer,255);
...
}
Be careful when using sockets, one read may don't give you the totality of the message you wait.
In case of structured messages, the protocol you define (you should define it well) have to give a message identifier at first, and you read until you receive sizeof( theSpecificMessage ), theSpecificMessage is identified by the identifier.

do_stuff most likely exited before the client thread did it's work.
The client thread uses stack allocated memory which then had been freed when do_stuff exited, and will be reused by some other code.
A solution to this would be to pass heap allocated memory to the client. If allocated dynamically the latter then needs to be freed by the client after it has done its work.

Related

why do I get, image can't be displayed because of error with my code?

I'm trying to load the image Koala.jpg (from the browser) that is specified by the user, but what ends up happing is a never ending load screen then an error with image can't be displayed. why is that?
void *connectionThread(void *socket_desc){
FILE* fd;
char buffer[256];
int newsockfd = *(int*)socket_desc;
int n;
magic_t myt = magic_open(MAGIC_ERROR|MAGIC_MIME_TYPE);
magic_load(myt,NULL);
bzero(buffer,256);
while (1)
{memset(buffer, 0, 255);n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");//error checking
printf("Here is the message: %s\n",buffer);
if((strncmp(buffer,"GET",3) == 0)){ //GET request
char *header = "HTTP/1.1 200 OK\r\nContent-Type: ";
//st_size filesize = stat(buffer, &st);
char *token = strtok(buffer," ");
if(token !=NULL)
token = strtok(NULL, " ");
token = strtok(token,"\n");
token = strtok(token,"/");
fd = fopen(token, "rb");
send(newsockfd,header,strlen(header),0);
printf("token is: %s\n",token);
printf("magic output: '%s'\n",magic_file(myt,token));
//write(newsockfd,"<",strlen("<"));
write(newsockfd,magic_file(myt,token),strlen(magic_file(myt,token))); //get Content-type
//write(newsockfd,">",strlen(">"));
write(newsockfd,"\r\n",strlen("\r\n"));
write(newsockfd,"Content-Length: ",strlen("Content-Length: "));
write(newsockfd,"780831\r\n\r\n",strlen("780831\r\n\r\n"));
}
if ((strncmp(buffer,"quit",4) == 0)) //quit
break;
n = write(newsockfd,"I got your message\n May I have another\n",40);
if (n < 0) error("ERROR writing to socket");
}
write(newsockfd,"Ok, I am quitting\n",18);
fclose(fd);
close(newsockfd);
magic_close(myt);
pthread_exit(NULL);
return 0;
}
Here is how I make the socket and bind it, in case something is off about that.
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno,c;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
puts("Created socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
c = sizeof(struct sockaddr_in);
pthread_t thread_id;
while((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*)&c))){
if (newsockfd < 0)
error("ERROR on accept");
pthread_create(&thread_id, NULL, connectionThread, (void *)&newsockfd);
}
close(sockfd);
return 0;
}
First, you have no synchronization on newsockfd. You pass the address of newsockfd to the thread, but then the main thread changes its value. You must never allow an object to be accessed in one thread while another thread is, or might be, modifying it. You break this rule with newsockfd.
Second:
printf("Here is the message: %s\n",buffer);
The %s format specifier is for C-style strings. At this point, buffer contains arbitrary image data.
Third: Your code reads some bytes from the incoming TCP connection and then acts as if it had read a message. But you never read a message. You have no code to read a message. If your application is going to use messages, you need to write code to receive a message. Just calling recv on the socket won't read a message because the TCP protocol is not a message protocol.
You probably have more issues, but those are the most serious.
Also, from a performance standpoint, it's awful to keep writing such small bits of data to a connection. Instead, assemble larger chunks in a buffer and use fewer calls to write.

Not receiving full data

I have the following socket code in C. I am trying to receive 70 bytes of data on each cycle. However, I am getting only 4 bytes of data. The full data is something like this (in hex):
4D43475000856308000004B2DE1F04009E00200100000000696CF7AB002F1A00000000
000000325C000402069BFDE70857E22502F41C000036000000DF0B0932100B09DC0719
What is the problem? I have tried to research many StackOverflow answers, but with no help.
The code is as below:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5000);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n,i;
unsigned int *buffer = malloc(1024);
n = read(sock,buffer,1023);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %.4x\n",*buffer);
n = write(sock,"MCGP",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
free(buffer);
}
There are quite a number of bugs in your code:
clilen = sizeof(cli_addr); needs to be moved inside of the while loop above the accept() call.
unsigned int *buffer should be unsigned char *buffer instead.
Why are you reading 1023 bytes when you are only expecting 70 bytes?
You need to call read() in a loop until you actually receive all of the bytes you are expecting. read() can return fewer bytes than requested. TCP is a byte stream, it has no concept of message boundaries, the read will return whatever bytes are currently available, so it will return at least 1 byte up to the requested number of bytes.
Your printf() call is only outputting the first 4 bytes of buffer, it is not outputting the full content of buffer. The return value of read() tells you how many bytes were actually received. Loop through the buffer outputting each byte individually.
write(sock,"MCGP",18) is a buffer overflow, since you are only passing 5 bytes (4 characters and the null terminator) but are telling it to send 18 bytes instead.
Try this instead:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno;
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
int pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR creating socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on bind");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
if (listen(sockfd, SOMAXCONN) < 0) {
perror("ERROR on listen");
exit(1);
}
while (1) {
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n, i;
unsigned char buffer[70], *p = buffer;
size_t len = 70;
do {
n = read(sock, p, len);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (n == 0) {
perror("DISCONNECTED unexpectedly");
exit(1);
}
p += n;
len -= n;
}
while (len > 0);
printf("Here is the message: ");
for (i = 0; i < 70; ++i)
printf("%.02x", buffer[i]);
printf("\n");
n = write(sock, "MCGP", 4);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}

multi-process in C : global variable's value

Here is the code from a website. It used multi-processing to create a server. My question is: will the parent process close(newsockfd) executed before the child process doprocessing(newsockfd) ?
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
===-=================
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
==========-==========================
code is from this website:
http://www.tutorialspoint.com/unix_sockets/socket_server_example.htm
When the process is forked, the gets a copy of the open set of file desriptors, and the reference count on the open filess is incremented accordingly. The close only happens in the parent process, so the child still maintains a reference to the open file. The order of execution doesn't really matter. On a multi-cpu system, it may happen truly simultaneously.
Global variables are not shared by forked child processes. A forked process runs in its own virtual memory space.

threaded server in c

I did not found an answer to my question before, nor did i know if that has an specific name for what i want to do, basically i have a program that runs a simulation, with graphical interface and calculations in the background, and i want to control it through commands with a tcp basic server/client but this means that i have to incorporate the server function inside the controlling function, so i made my server inside a thread and i am running something in the main function, while i call the server function in a thread just for testing, but i cannot send anything to the server, my client application does not get a response, and the server does not receive anything... the code is messy because i am testing a lot of stuff in it, and the identation is messy too...
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
int test= 0;
void threadServer(){
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, c;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while(c){
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr,
&clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
//if(buffer[0]==t){
//c=0;
//exit(1);
//}else{
//c=1;
//}
printf("Here is the message: %s\n",buffer);
/* Write a response to the client */
n = write(newsockfd,"I got your message",18);
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
test =1;
}
//return 0;
}
void main(){
pthread_t threads[1];
int rc;
long t;
char k;
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, threadServer, (void *)t);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
while(1){
printf("type any key:\n");
scanf("%c",&k);
printf("you typed %c\n", k);
printf("testing server thread : %d\n", test);
}
/* Last thing that main() should do */
pthread_exit(NULL);
}

full duplex communication between server & client

I want to make a code for full duplex communication between server & client using this code.
I got error in receive-message thread from server side & in send-message thread from client side.
please help me to solve this errors & suggest me if any other changes are required.
Thanks :)
server.cpp
int newsockfd, n;
void error(const char *msg)
{
perror(msg);
exit(1);
}
void* recvFn( void* data )
{
char buffer[256];
while(n==0){
memset( buffer, sizeof(buffer), 0);
n = recv(newsockfd,buffer,255,MSG_PEEK);
if(n>0){
printf("cliet: ");
printf("%s",buffer);
}
}
return NULL;
}
void* sendFn( void* data )
{
char temp[255], buffer[255];
while(n==0){
memset( buffer, sizeof(buffer), 0);
fgets(temp,255,stdin);
sprintf(buffer,"clent: %s",temp);
n = send(newsockfd,buffer,strlen(buffer),MSG_EOR);
}
return NULL;
}
int main(int argc, char *argv[])
{
int sockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
pthread_t recvThread, sendThread;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
memset( &serv_addr, sizeof(serv_addr), 0);
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
int on = 1;
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof( on ) ) != 0 ) {
close( sockfd );
return -1;
}
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
n = 0;
int rc;
rc = pthread_create( &recvThread, NULL, recvFn, NULL);
if(rc){
printf("error in receive-message thread\n");
return -1;
}
rc = pthread_create( &sendThread, NULL, sendFn, NULL);
if(rc){
printf("error in send-message thread\n");
return -1;
}
close(newsockfd);
close(sockfd);
pthread_cancel(recvThread);
pthread_cancel(sendThread);
return 0;
}
client.cpp
int sockfd, n;
void* recvFn( void* data )
{
char buffer[255];
while( n==0 ){
memset( buffer, sizeof(buffer), 0);
n = recv(sockfd,buffer,255,MSG_PEEK);
if(n>0){
printf("server: ");
printf("%s",buffer);
}
}
return NULL;
}
void* sendFn( void* data )
{
char temp[255], buffer[255];
while( n==0 ){
memset( buffer, sizeof(buffer), 0);
fgets(temp,255,stdin);
sprintf(buffer,"clent: %s",temp);
n = send(sockfd,buffer,strlen(buffer),MSG_EOR);
}
return NULL;
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int portno;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
pthread_t recvThread, sendThread;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
portno = atoi(argv[2]);
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset( &serv_addr, sizeof(serv_addr), 0);
serv_addr.sin_family = AF_INET;
memcpy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on connecting");
n = 0;
int rc;
rc = pthread_create( &sendThread, NULL, sendFn, NULL);
if(rc){
printf("error in send-message thread\n");
return -1;
}
rc = pthread_create( &recvThread, NULL, recvFn, NULL);
if(rc){
printf("error in receive-message thread\n");
return -1;
}
close(sockfd);
pthread_cancel(recvThread);
pthread_cancel(sendThread);
return 0;
}
Your pthread_mutex operations are completely pointless. You're referring only to local variables inside the mutex lock other than n, which should be local in each thread and newsockfd which also should not be global, see below. (Don't you think that a function which calls recv should have a local variable to capture the number of bytes read, and not share that silly little temporary variable globally with other threads?)
Your main thread is in a while loop, creating threads like crazy. Also, inside that loop it has closed the one and only accepted socket, right after creating the threads.
You forgot to put your accept inside the loop, evidently.
Also you seem to think that the main loop will somehow wait for the pair of threads to terminate before launching new ones. You are missing pthread_join calls to wait for the threads finish communicating. If you want the thread to keep going while the main loop accepts new connections using new threads, you should make those threads detached with pthread_detached or using a thread-creation attribute which makes them detached. Non-detached threads which are not pthread_join-ed continue to occupy resources.
Speaking of shutdown, is it really the correct condition that the threads keep looping while n == 0? As soon as n is set to nonzero by one of the threads, the shutdown condition is met. But a nonzero value is normal: some bytes written or read. Your reader should terminate the loop when there is a fatal receive error on the socket, or the read returns zero.
Also, you are evaluating n == 0 outside of the mutex!
If you want to accept multiple concurrent connections, each with its pair of threads, then you cannot use a single global socket. You have to give each pair of threads their own socket. The two threads within each pair do not have to use a mutex to share the socket. The socket calls are thread-safe in the kernel and the threads are not both doing reads or writes; one is reading and one is writing.
Other problems
Your sender keeps sending uninitialized garbage: a buffer that was never set to contain any data.
You have a bzero of 256 bytes on an array of 255 bytes.
Also
Don't use bzero (or bcopy, etc). It's a BSD-ism from the 1980's. The C language was finally standardized in 1989 by ANSI and soon after in 1990 by ISO. At that time, it already had the library functions memset, memcpy and memmove.
I think 22 years later, it is safe to retire bcopy, dontcha think?

Resources