Linux C: segfault error 4 in libmysqlclient.so.18.0.0 - c

I'm trying to implement a multithreaded tcp server with the following code.
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( 8888 );
//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);
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;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( sniffer_thread , NULL);
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 newsockfd = *(int*)socket_desc;
int read_size;
char *message , buffer[2000];
int n;
struct auth details;
char* reply;
char cmd[100] = {0};
//Receive a message from client
while( (read_size = recv(newsockfd , buffer , 2000 , 0)) > 0 )
{
printf("Incoming data: %s", buffer);
if(parseData(cmd, buffer, "/", "-")) /* If received data is compliant */
{
details = authenticate(cmd);
if (details.verified) // If said user can execute this command.
{
reply = execute(cmd); // Execute.
n = write(newsockfd, reply, strlen(reply));
if (n < 0) { error("ERROR writing to socket"); }
free(reply);
reply = NULL;
}
else // Authentication failed.
{
n = write(newsockfd, details.error_msg, strlen(details.error_msg));
if (n < 0) { error("ERROR writing to socket"); }
else{
if(debug) printf("sent: %s\n", details.error_msg);
}
}
}
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
The authenticate function is defined in an implementation file:
struct auth authenticate(const char* const command)
{
struct auth data;
char* db_pwd;
char* perm;
char* username = "testUser";
char query[200] = {0};
data.verified = FALSE;
data.error_msg = "";
printf("in auth\n");
MYSQL_ROW row;
snprintf(query, 200, "SELECT password FROM userlist WHERE user='%s'", username);
if ((row = mysql_fetch_row(run_query(query)))) // if user is on list
{
db_pwd = row[0];
if(!strcmp(db_pwd, password))
{
if (!(strcmp(command, "test")))
{
data.verified = TRUE;
}
}
}
return data;
}
I have a working single threaded version of this program(main) with the same implementation file, the segmentation fault occurs only with the multithreaded version.
Am I doing something wrong in my code?
How should I proceed with debugging?
Any ideas would be appreciated.

Read documentation of MySQL C API, notably ยง 23.8.12 C API Threaded Function Descriptions It internally uses a socket connection to the mysqld server process, so you have to serialize all MySQL functions.
So, define your global mutex, and protect all the functions doing mysql calls with that mutex (from a request to fetching all the rows of the reply). Better yet, design your application so that only one single thread (usually the main one) is using mysql functions.
Compile with all warnings and debug info (gcc -Wall -g). Use the debugger (gdb) and perhaps valgrind
If unfamiliar with mutexes, you might want to read a pthread tutorial

Related

Multipleclient Server: quitfunction

I have some problems with my Server/Client.
If multiple people connect to my server, and one of them quit the connection to the server, all other, which are also connected to the server, lose their connection to.
void *connection_handler(void *);
extern int check_err_buffer(int sock);
extern error_t *error_buffer;
extern invalid_user_input_t invalid_user_input;
regex_t regex;
int main(int argc, char *argv[]) {
//init KVS
init();
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
//Create socket
socket_desc = socket(AF_INET, SOCK_STREAM | O_NONBLOCK, 0);
int opts;
opts = fcntl(socket_desc,F_GETFL);
opts = opts & (~O_NONBLOCK);
fcntl(socket_desc,F_SETFL,opts);
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(8503);
//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);//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while (1) {
puts("waiting for client...");
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;
pthread_create(&sniffer_thread, NULL, connection_handler, (void *) new_sock);
//Now join the thread , so that we dont terminate before the thread
//pthread_join(sniffer_thread, NULL);
puts("Handler assigned");
}
if (client_sock < 0) {
perror("accept failed");
return 1;
}
return 0;
}
In the main function I accept the different connection from the clients.
I have more functions, which I didn't put in, because they are not so relevant for this problem.
In the second part I will handle some cases. I look if the client type the letter 'q', if it's true, I will close the connection with close().
But in all cases, it close the server, and all connections are lost.
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc) {
//Get the socket descriptor
int sock = *(int *) socket_desc;
char *message, client_message[3000];
puts("sending welcome msg to client...");
write(sock, message, 3000);
int reti;
//compile a regexp that checks for valid user input
regcomp(&regex, "([dg] [0-9]+)|([v] .+)|(p [0-9]+ .+)|q", REG_EXTENDED);
//Receive a message from client
char *input[3];
while(1){
//wait for some client input
recv(sock, client_message, 2000, 0);
//check the input with the regexp
reti = regexec(&regex, client_message, 0, NULL, REG_EXTENDED);
if (!reti) {
//tokenize the client input with \n as a delim char
char *token = strtok(client_message, " ");
int i = 0;
while (token) {
input[i] = token;
token = strtok(NULL, " ");
i++;
}
//quit operation
if (strcmp(input[0], "q") == 0) {
//if a client quits, the server dies. TODO: fix
puts("quitting");
//free(socket_desc);
close(socket_desc);
return 0;
}
//user input does not match regexp, try again..
} else if (reti == REG_NOMATCH) {
error_buffer = invalid_user_input;
check_err_buffer(sock);
usleep(100);
write(sock, " ", 2);
}
}
//Free the socket pointer
free(socket_desc);
return 0;
}
On the client side i test if message[0] == 'q' and I close the socket.
I would be very happy if i will get some help or hints to solve this problem. Thank you
As here
new_sock = malloc(1);
the code allocates 1 byte only, this following line
*new_sock = client_sock;
writes to invalid memory, as an int is assigned, and sizeof int bytes are written to where new_sock points. By definition sizeof int is at least 2, probably more, With this undefined behaviour is invoked. Anything may happen from then on.
To fix this do
new_sock = malloc(sizeof *new_sock);
instead.
Inspecting the return value of functions is debugging for free. close(socket_desc); is nonsense and definitely would return -1 and set errno to EBADFD.
Replace
close(socket_desc);
by
if (-1 == close(socket_desc))
{
perror("close() falied");
}
to see how the code as it stand fails.

Sending data from server to client socket programming

I have just started learning socket programming.
Currently the server and the client are on the same workstation and everything seems to work. The server is running in c programming and my client is an android program. I managed to have a one way connection, sending data from client to server. I would like to send some string back to client.
Please advice me.
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c;
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( 7800 );
//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);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
pthread_t thread_id;
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
if( pthread_create( &thread_id , NULL , connection_handler , (void*) &client_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( thread_id , NULL);
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 read_size;
char *message , client_message[2000];
//Send some messages to the client
message = "Greetings! I am your connection handler\n";
write(sock , message , strlen(message));
message = "Now type something and i shall repeat what you type \n";
write(sock , message , strlen(message));
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//end of string marker
client_message[read_size] = '\0';
printf("%s\n", client_message);
//Send the message back to client
write(sock , client_message , strlen(client_message));
//clear the message buffer
memset(client_message, 0, 2000);
}
if(read_size == 0)
{
//puts("Client disconnected");
//fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
There are different ways to transmit data to another socket and it doesn't matter if it's either a server or a client.
write
As you did in your code, you can use the system call:
ssize_t write(int fd, const void *buf, size_t count);
It writes from the buf to the file related to the file descriptor fd. The return value will tell you if the message was sent correctly.
send, sendto, sendmsg
This is the second way you can send data to a socket. The only difference between write and send is the argument flags:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
but if you set flag to 0, write and send will work in the same way.
sendto and sendmsg are quite different from send because they have more arguments. You can get all information from man pages available online or in Linux.
http://man7.org/linux/man-pages/man2/send.2.html
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
is wrong; you probably want to check >= 0 or (even better) express this in another way.
The lone
write(sock , message , strlen(message));
is not good:
you should check the error code
it will be very difficult for the receiver to split the result.
write() will kill your program with SIGPIPE when the other end has been closed
I suggest something like
bool send_data(int fd, void const *data, size_t len)
{
while (len > 0) {
ssize_t l = send(fd, data, len, MSG_NOSIGNAL);
if (l > 0) {
data += l;
len -= l;
} else if (l == 0) {
fprintf(stderr, "this is ugly and can not happen...\n");
break;
} else if (errno == EINTR) {
continue;
} else {
perror("send()");
break;
}
}
return len == 0;
}
and for string datatypes
bool send_string(int fd, char const *str)
{
size_t l = strlen(str);
uint32_t l_be = htobe32(l);
if ((uint32_t)(l) != l)
return false;
return (send_data(fd, &l_be, sizeof l_be) &&
send_data(fd, str, l));
}
For receiving, you can implement recv_data() similarly to send_data() above. Depending on your memory allocation strategy, you can implement either
bool recv_string(int fd, char *str, size_t max_len, size_t *len)
{
uint32_t l_be;
size_t l;
if (!recv_data(fd, &l_be, sizeof l_be))
return false;
l = be32toh(l_be);
if (l >= max_len)
return false;
if (!recv_data(fd, str, l))
return false;
str[l] = '\0';
if (len)
*len = l;
return true;
}
or write something which malloc() memory for the received data after reading the length.
Now, you can do on one side:
if (!send_string(fd, "foo") ||
!send_string(fd, "bar") ||
!recv_string(fd, resp, sizeof resp, NULL))
error();
and on the other one
if (!recv_string(fd, req0, sizeof req0, NULL) ||
!recv_string(fd, req1, sizeof req1, NULL) ||
!send_string(fd, handle_request(req0, req1)))
error();

Connection Refused even after adding a new Firewall rule

I am trying to connect to my local UNIX server i made from another remote device. the Server is up and listening to the port i specified. i also added a new firewall rule to open that port but still my client cannot connect. it shows ERROR CONNECTION REFUSED
here is my server code
int main() {
int fd, i,svclient,rval,msg;
int clients[10], num_clients;
fd_set read_set,write_set;
char buf[100];
struct sockaddr_in addr;
if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(4001);
//strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
//strcpy(addr.sun_path, NAME);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
exit(-1);
}
printf("Bind complet...\n");
if (listen(fd, 20) == -1) {
perror("listen error");
exit(-1);
}
num_clients = 0;
int size = sizeof(fd);
while (1) {
int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
for (i = 0; i < num_clients; i++) { //at first this part will not excute
FD_SET(clients[i], &read_set);
}
select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(fd, &read_set)) {
if ( (clients[num_clients++] = accept(fd,(struct sockaddr*)&client_addr,&addrlen)) == -1) {
perror("accept error");
continue;
}
/*printf("incoming message..................... !\n \n");*/
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
for (i = 0; i < num_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
msg = read(clients[i], buf, sizeof(buf));
if(msg > 0){
buf[msg] = 0;
int savedclnt = clients[i];
printf("%s \n \n", buf);
/*for(int p=0;p<num_clients;p++)
{
if( clients[p]!= savedclnt){
write(clients[p],buf,msg);
}
}*/
}
}
}
}
}
and my client
int main( )
{
struct uci_context *uci;
uci = uci_init();
int sockfd;
int ret;
struct sockaddr_in dest;
struct addrinfo hint, *res = NULL;
struct hostent *host;
char *hostip;
char *string;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
puts("Unble to create socket");
exit(1);
}
hostip = ucix_get_option(uci, "pack_mon", "pack_monitoring", "address");
string = ucix_get_option(uci, "pack_mon", "pack_monitoring", "port");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(string));
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
printf(" %s- %s\n", hostip, string );
if(isdigit(hostip[0])){
ret = getaddrinfo(hostip, NULL, &hint, &res);// this is more efficient than inet_addr
if (ret) {
exit(1);
}
}else if( (host = gethostbyname(hostip)) != 0){
memcpy((char*)&dest.sin_addr , (char*)host->h_addr , (sizeof dest.sin_addr)+1);
}else{
exit(1);
printf("cannot resolve ip address");
}
if ( connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0 )
{
perror("ERROR Connecting" );
exit(1);
}else{
printf("Port number %s is open.....\n",string);
}
char *message;
message = "help";
write(sockfd,message,strlen(message));
close(sockfd);
freeaddrinfo(res);
return 0;
}
FIREWALL RULE
sudo iptables -I INPUT -p tcp --dport 4001 -j ACCEPT
Error is :
192.168.10.155- 4001
ERROR Connecting: Connection refused
and this logs are coming from this codes :
printf(" %s- %s\n", hostip, string );
perror("ERROR Connecting");
exit(1);
Your client has no code to specify the IP address it wants to connect to. All the code that could do that has been commented out.
Update: Now your bug is here:
strncpy((char*)&dest.sin_addr , (char*)host->h_addr , sizeof dest.sin_addr);
The strncpy function is only suitable for C-style strings. You need to use memcpy or something similar. This will only copy part of the IP address if any octet other than its last one (in network byte order) is zero.
Update: Now your bug is here:
printf("%d\n", connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) < 0);
perror("hmmmm" );
exit(1);
This calls connect, then calls printf and then calls perror. The problem is, the call to printf can modify errno even if it succeeds. Thus your call to perror can print a totally irrelevant error message.

Implementing a proxy (both client part and server part) in C (with socket programming)

I am currently working on a Proxy that should get the browser's request, forward it to the server and then return the server's reply so that the requested page can download.The proxy should support both HTTP 1.0 and 1.1.
I have to write this program in C, with socket programming, but I am new in both (I have only ever programmed in Ada). So I tried to write something, but as soon as I run my program and try to connect, I get a "Segmentation fault" error and I don't know what it could mean. I've read that it was about pointers/strings and memory, but I don't know why I'm getting these errors.
here is my code:
#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<netdb.h> //hostent
int main(int argc , char *argv[])
{
int socket_desc , new_socket ;
struct sockaddr_in server , client;
char message_from_browser[2000];
int len;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c;
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
if (new_socket<0)
{
perror("accept failed");
return 1;
}
close(socket_desc); // don't need this anymore
puts("okay dude??");
if (recv(new_socket, message_from_browser, 2000, 0)<=0)
{
puts("error: connection");
}
puts(message_from_browser);
puts ("Request Received!");
puts("okay huhhh??");
// oKAY i receive the request! Now extract the hostname from the request!
char my_hostname[256];
int j=0;
puts("we created j so");
// doesn't workkkkk: Segmentation error
while (j < strcspn(strstr(message_from_browser, "www."), "/"))
{
my_hostname[j] = strstr(message_from_browser, "www.")[j];
j++;
puts(j);
}
puts("hostname found! It is: \r");
puts(my_hostname);
char *hostname = my_hostname;
char ip[100];
struct hostent *he;
struct in_addr **addr_list;
int i;
if ( (he = gethostbyname( hostname ) ) == NULL)
{
//gethostbyname failed
herror("gethostbyname");
return 1;
}
//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++)
{
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
}
printf("we now have the ip we want to connect to and it is: %s \n", ip);
// CLIENT SIDE
struct sockaddr_in actual_server;
char server_reply[2000];
int socket_client;
socket_client = socket(AF_INET , SOCK_STREAM , 0);
if (socket_client <0 )
{
puts("error: couldn't create socket");
}
// remove the "http" from the message of the browser
/*char message_from_browser_edited[2000];
char token_1[1993];
char token_2[4];
int k=0;
int l=0;
int m=0;
while (k < strcspn(message_from_browser, "http"))
{
token_1[k] = message_from_browser[k];
k++;
}
while (l < 1992)
{
my_hostname[l] = strstr(message_from_browser, "http")[l];
l++;
}
for (m=0; m<=1992; m++)
{
if (m<=3)
message_from_browser_edited[m] = token_1[m] ;
else
message_from_browser_edited[m] = token_2[m-4];
}
puts("We edited the browser's message");
puts(message_from_browser_edited);*/
// now we have the true message from the browser
if (write(socket_client, message_from_browser, 2000 )<0)
{
puts("error: wouldn't write :(");
}
puts("written!");
// client reaching actual server
actual_server.sin_addr.s_addr = inet_addr(ip); // ip is the result of gethostbyname
actual_server.sin_family = AF_INET;
actual_server.sin_port = htons( 80 ); // it's 80 bc the client side of the proxy is now trying to access the actual internet
if (connect(socket_client , (struct sockaddr *)&actual_server , sizeof(actual_server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected!!!");
if( send(socket_client , message_from_browser, 2000 , 0) < 0)
{
puts("Send failed :( ");
return 1;
}
puts("Data Send!!!!");
//Receive a reply from the server
if( recv(socket_client, server_reply , 2000 , 0) < 0)
{
puts("recv failed");
}
puts("Reply received\n");
puts(server_reply);
puts(" ");
// BACK TO THE SERVER SIDE that will send the message back to the browser.
if (send(new_socket, server_reply, 2000, 0) == -1)
{
perror("send");
close(new_socket);
exit(0);
}
close(new_socket); // parent doesn't need this
} // this is for the while
return 0;
} // this is the main
I've scattered a few messages here and there to pinpoint where exactly the problem is and I found out that it's where I try to extract the host name from the browser's request (I put a comment here that says I got a Segmentation Error). This is weird because it used to work before I made other changes, so I put the changes in comments in hope that it would work again but it doesn't... So I really don't understand what could be wrong. I know that the error is in the while loop's statements but I don't know what's wrong with what I wrote ((j < strcspn(strstr(message_from_browser, "www."), "/"))). Is there any way to fix that issue? And am I even doing the right thing for the proxy to work?
Thank you!

client makes multiple connections to server

I have updated my code to this based on research:
while (number_of_connections--) {
client_sock = socket(AF_INET , SOCK_STREAM , 0);
if (connect(client_sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
printf("socket %d created\n", client_sock);
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;
}
}
Then I'm handling it with this function:
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size, cursor;
char *message , client_message[2000];
//Send some messages to the client
char handshakeBuf[sizeof(handshake)];
memcpy(handshakeBuf, &handshake, sizeof(handshake));
handshake.a++;
handshake.c = 0xac;
handshake.d = 0x0d;
//Send some data
if( send(sock , handshakeBuf , sizeof(handshakeBuf) , 0) < 0)
{
puts("Send failed");
}
//keep communicating with server
while(1)
{
//Receive a reply from the server
if( recv(sock , client_message , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(client_message);
}
close(sock);
return 0;
}
Now my problem is why does it suddenly stop when it reaches the 4th connection?
Original Question
I am trying to write my first C client. I needed to create 4 connections to the server from one client to simulate 4 clients connected where each connection of course has its own handler.
Here is what I have so far:
void connect_to_server(struct sockaddr_in server);
int main(int argc , char *argv[])
{
int number_of_connections, x;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("ipaddress");
server.sin_family = AF_INET;
server.sin_port = htons( port );
number_of_connections = 4;
for ( x = 0; x < number_of_connections; x++ ) {
connect_to_server(server);
}
return 0;
}
void connect_to_server(struct sockaddr_in server) {
int sock;
char message[1000] , server_reply[2000];
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
while(1)
{
scanf("%s" , message);
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
}
if( recv(sock , server_reply , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(server_reply);
}
close(sock);
}
Well I'm obviously also new to C. So what is wrong? Should I declare more sockets like: int sockA, sockB, sockC, sockD or I guess its the while loop inside the connect_to_server?
It seems the new version of the implementation uses multithreading: pthread_create(...) function call. But is there an implementation of waiting after the threads are created?
For example, the waiting can be implemented:
by using pthread_join(...) function call;
by waiting for specific key press event using getchar() function call.
Notes
Please be careful with these statements:
if (send(sock, handshakeBuf, sizeof(handshakeBuf), 0) < 0)
if (recv(sock, client_message, 2000 , 0) < 0)
The send() and recv() functions do not guarantee that the entire buffer will be sent/received after one function call. The functions return the actual number of sent/received bytes.
Please introduce analysis of the returned value for send() and recv() function calls: continue sending if not all bytes are sent, continue receiving if "not enough" bytes are received. Also, there is an article related to the some basics of the network programming: TCP/IP client-server application: exchange with string messages.

Resources