In Linux(Debian 7), when I run the server, the pointer to array *arg for *doSomething it crashes with segmentation fault.
(Line int *arg = malloc(sizeof(*arg));)
When I run the same code in Solaris, it runs like a charm.
Everything is compiled at its own respective OS (running at Solaris, compiled at Solaris, etc) with no errors or warnings.
A code snippet of the main body of the server without the doSomething method
int main(int argc, char *argv[])
{
int sockfd, portno,pErr;
socklen_t clilen;
//char buffer[256];
//char servPlay[10];
struct sockaddr_in serv_addr, cli_addr;
int n;
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");
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");
while(1) {
int newsockfd;
printf("Listening\n");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("Client %s connected\n", inet_ntoa(cli_addr.sin_addr));
int *arg = malloc(sizeof(*arg));
if(arg ==NULL) {
fprintf(stderr, "No memory for thread\n");
}
*arg=newsockfd;
pErr = pthread_create(NULL,NULL,doSomething,arg);
if(pErr!=0)
{
error("Cannot cread thread\n");
//break;
}
}
close(sockfd);
return 0;
}
More probably than not mnunberg hit the mark and the crash happens in pthread_create() rather than the line you think.
man pthread_create:
Before returning, a successful call to pthread_create() stores the
ID of the new thread in the buffer pointed to by thread; this identifier
is used to refer to the thread in subsequent calls to other pthreads
functions.
It would be pointless allowing to pass a NULL pointer as the first argument (thread).
Related
I'm trying to write a client-server program in C. For now I have a connection between the server and the client but for some reason nothing happens or prints after the "connected" print.
I've tried sample printing before and after the "connected" but nothing shows on my shell.
my server:
int main(void)
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);//Af_INet is protocol tcp np? ip? - this creates an empty socket
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
{
printf("setsockopt failed\n");
exit(0);
}
// calls to bind(), listen() and accept() here
memset((char *) &serv_addr, 0, sizeof(serv_addr));
portno = 8888;
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)
{
printf("bind failed\n");
exit(0);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
printf("accept failed\n");
exit(0);
}
//end calls
printf("[Server] Connected\n"); // nothing prints before or after this
int n;
char query[BUFFER_SIZE]={0};
char result[BUFFER_SIZE]={0};
char *hello = "Hello from client";
send(newsockfd, hello , strlen(hello) , 0 ); //write also doesn't work
printf("Hello message sent\n");
n = read( newsockfd, query, BUFFER_SIZE);
printf("%s\n",query );
close(newsockfd);
close(sockfd);
my client:
int main(void)
{
int sockfd, portno;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
//get host and connect
portno = 8888;
server = gethostbyname("localhost");
if (server == NULL)
{
printf("gethostbyname failed\n");
exit(0);
}
memset((char *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((void*)&serv_addr.sin_addr.s_addr, (void*)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("connect failed\n");
exit(0);
}
//end connect
printf("client here");//doesn't show on shell screen
printf("[Client] Connected\n");//shows on shell screen
int n;
char *hello = "Hello from client";
char query[BUFFER_SIZE]={0};
char result[BUFFER_SIZE]={0};
send(sockfd, hello, strlen(hello), 0);
printf("Hello message send\n");
n=read(sockfd,query,BUFFER_SIZE);
printf("%s\n",query);
close(sockfd);
I compile these with:
gcc -Werror -std=c99 server.c -o server
gcc -Werror -std=c99 client.c -o client
Also, I ran ./server before ./client , the shell screens show "Connected" on both client and server screens and that's it no matter what I write on the screen (either client's or server's)
Any help would be appreciated!
so i have a very basic tcp server which has two threads listening on two separate ports. However, when the code runs the second thread is never created and it appears that the first thread is actually blocking the whole program from creating the next thread. Here is the code... (quite simple)
void *Listener1();
void *Listener2();
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL,Listener1(), NULL);
pthread_create(&thread2, NULL,Listener2(), NULL);
sleep(50);
return 0;
}
void *Listener1()
{
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("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(12346);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}
void *Listener2()
{
puts("hi)");
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("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(12345);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}
Cake a close look at
pthread_create(&thread1, NULL,Listener1(), NULL);
// ^^
// causes the function to be called
Here you don't pass a pointer to the Listener1 function, you are actually calling it, and its returned value would be used as the function pointer to the thread function, if it ever returned.
You should instead pass a pointer to the function:
pthread_create(&thread1, NULL,&Listener1, NULL);
I am starting to use aio to write a simple client server program.My client program:
int main(int argc, char const *argv[])
{
int port = 6000;
struct sockaddr_in my_address;
memset(&my_address, 0, sizeof(my_address));
my_address.sin_family = AF_INET;
my_address.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1
my_address.sin_port = htons(port);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr*)&my_address, sizeof(my_address));
char * str = "hello";
struct aiocb my_aio;
memset((void*)&my_aio, 0, sizeof(struct aiocb));
my_aio.aio_fildes = fd;
my_aio.aio_buf = str;
my_aio.aio_nbytes = strlen(str);
aio_write(&my_aio);
return 0;
}
My server program:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening 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);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
sleep(5);
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
return 0;
}
I expect my server side to print out hello, but it does not. Thanks in advance.
Your code works otherwise, but your main is exited before the asynchronous write has completed; thus the socket is closed before the completion of asynchronous write. I did as little as add a perror("aio_write") after the aio_write call to find out what error it was giving if any, and now hello was successfully sent to the server.
You'd probably want to use aio_suspend to ensure that any outstanding operations are completed before exiting the main.
when i run both client and server i get this as result:
on server
Server is on
Client: XXX.X.X.X accepted
(that's the point that the program pauses until I type ctrl+C in client)
I try to get in while
I get in while
Client
AI Choise:Scissor
AI:Wins ratio 0,Looses ratio 0,Ties ratio 1
I get in while
Client
AI Choise:Scissor
AI:Wins ratio 0,Looses ratio 0,Ties ratio 2
on client
1)--> Paper
2)--> Scissor
3)--> Rock
4)--> Quit
^C
my code:
Server:
int main(int argc, char *argv[]){
printf("\nServer is on\n");
int sockfd, newsockfd, portno;
socklen_t clilen;
int Client_Choice;
struct sockaddr_in serv_addr, cli_addr;
int n,Who_Wins;
int ai_wins=0,ai_looses=0,ties=0,total=0,ai_win_ratio=0,ai_looses_ratio=0,ai_ties_ratio;
time_t t;
srand((unsigned) time(&t));
if (argc < 2) {
fprintf(stderr,"\nERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
error("\nERROR opening socket\n",sockfd);
}
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("\nERROR on binding\n",sockfd);
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
if (newsockfd < 0){
error("\nERROR on accept\n",sockfd);
}
char *cli_IP = malloc(sizeof(cli_addr.sin_addr.s_addr));
if (!cli_IP){
error("\nCould not allocate memory for conversion.\n",sockfd);
}
inet_ntop( AF_INET , &cli_addr.sin_addr.s_addr , cli_IP , INET_ADDRSTRLEN );
printf("\nClient: %s accepted\n",cli_IP);
printf("I try to get in while");
while(Client_Choice!=4){
printf("I get in while");
n= read( newsockfd, &Client_Choice, sizeof(Client_Choice) );
if(n < 0) {
error("\nERROR reading from socket\n",sockfd);
}
.
.
.
}
close(newsockfd);
close(sockfd);
return 0;
}
client
int main(int argc, char *argv[]){
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int send;
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket\n");
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((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 connecting\n");
}
while(send < 1 ||send > 4){
printf("\n\t1)--> Paper\n\t2)--> Scissor\n\t3)--> Rock\n\t4)--> Quit\n");
scanf("%d",&send);
n = write(sockfd,&send,sizeof(send));
if (n < 0){
error("ERROR writing to socket\n");
}
n = read(sockfd,&send,sizeof(send));
if (n == 0){
error("ERROR reading from socket\n");
}
}
close(sockfd);
return 0;
}
Your server is blocked waiting the message from the client. You have not reserved resources for dealing with several clients and only have a single process serving a single client (using the connection socket from accept(2)). That's the reason of it to appear blocking. In a normal server scenario, a new process is spawned by a fork(2) system call to deal with the socket obtained from accept(2) while the main process continues to accept(2) connections on the socket used for accepting new connections. As you are dealing with two sockets in server, but not attending the socket descriptor where accept(2) connections come in, it appears to be blocked, but it is actually ready to accept the commands from the active client. This is what is called a sequential server (it doesn't allow a connection before the first one terminates).
By the way, send is uninitialized before use in first while (send < 1 || send > 4) sentence so in case you get it casually equal to 2 (for example) you won't get client code into the while at all. This is only a point, probably there will be more. Why have you used different names for the message type interchanged between server and client? this makes more difficult to search for errors.
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.