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.
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!
I want to make a client and connect it to a server. I know that client process starts running before server so I do connection in infinite loop until it will be accept. Then I want to enter messages to client and send them to server, which will print them on screen. I removed all error detection from code to make it shorter, I know they have to be there. I am trying to do it like this, but server receives nothing and client can't do second connection.
Server
int main(int argc, char *argv[])
{
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sockfd, 5);
clilen = sizeof(cli_addr);
while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0)
{
read(newsockfd, buffer, 255);
close(newsockfd);
}
close(sockfd);
return 0;
}
Client
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr;
char buffer[256];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
while (1) {
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}
close(sockfd);
return 0;
}
I don't know just how you've compiled your code but if you had set up the warning flag (-Wall in gcc) you would have gotten this warning
server.c: In function ‘main’:
server.c:33:44: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
Acting by it, I changed, this ..
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
To .. (notice the extra parentheses)
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
I got no more additional warnings, and the server caught the client's message.
Here is the server I ran while debugging this (This is basically your code with slight alterations)
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
int nbytes = 0;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
//serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(5007);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (listen(sockfd, 5) <0) { }
clilen = sizeof(cli_addr);
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
while ((nbytes = read(newsockfd, buffer, sizeof(buffer)))<0) {
sleep(1);
}
printf("client sent: %s", buffer);
}
close(newsockfd);
close(sockfd);
return 0;
Another problem was that we have to create socket each time we do connect in client, like:
while (1) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}
I am a newbie in libevent, my program below is quite simple. I want to call bubufferevent_write several times, but is seems that it works only for the 1st time.
int main(int argc, char const *argv[])
{
struct sockaddr_in serv_addr;
struct hostent *server;
int portno = atoi(argv[2]);
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
}
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);
struct event_base* base = event_base_new();
evutil_socket_t fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
struct bufferevent* con_conn = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(con_conn,NULL,NULL,NULL,NULL);
bufferevent_enable(con_conn,EV_READ|EV_WRITE|EV_PERSIST);
bufferevent_socket_connect(con_conn,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
int enable = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
printf("TCP_NODELAY SETTING ERROR!\n");
char data[5] = "sss";
int i;
for (i = 0; i < 2; ++i)
{
int rc = bufferevent_write(con_conn,data,5);
printf("rc is %d\n", rc);
}
event_base_dispatch(base);
return 0;
}
My server side:
void error(char *msg)
{
perror(msg);
exit(1);
}
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");
//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");
listen(sockfd,5);
clilen = sizeof(cli_addr);
printf("waiting...\n");
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 have written a sample socket program in C on Linux.
The server is single process server.
The program is simple where the server is running and the client connects to the server waiting on accept() call.
When the server accepts the client request it sends some string to the client using write call.
Server Code:
#define MAXHOSTNAME 256
#define MAX_CONN 10
void single_process_server(unsigned int portNumber)
{
int listenSockFd, acceptSockFd, portNo;
socklen_t clilen;
char buffer[256] = "Connected";
struct sockaddr_in srvInfo;
int n;
char sysHost[MAXHOSTNAME+1]; // Hostname of this computer we are running on
if((listenSockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
close(listenSockFd);
error("ERROR opening socket");
}
bzero((char *) &srvInfo, sizeof(srvInfo));
portNo = portNumber;
srvInfo.sin_family = AF_INET;
srvInfo.sin_addr.s_addr = htonl(INADDR_ANY);
srvInfo.sin_port = htons(portNo);
if (bind(listenSockFd, (struct sockaddr *) &srvInfo, sizeof(srvInfo)) < 0)
{
close(listenSockFd);
error("ERROR on binding");
}
listen(listenSockFd,5);
while(1)
{
clilen = sizeof(srvInfo);
if((acceptSockFd = accept(listenSockFd, (struct sockaddr *) &srvInfo, &clilen)) < 0)
{
error("ERROR on accept");
}
if((n = write(acceptSockFd,buffer,255)) < 0)
{
error("ERROR writing to socket");
}
close(acceptSockFd);
}
close(listenSockFd);
}
int main(int argc, char* argv[])
{
unsigned int portNo= 0;
portNo = 444;
single_process_server(portNo);
return(0);
}
The client receives the string using read call.
Client Code:
void simple_internet_client(char hostip[], unsigned int portNo)
{
int sockFd, portno, n;
struct sockaddr_in srvInfo;
struct hostent *server;
char buffer[256];
portno = portNo;
if((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
error("ERROR opening socket");
}
if((server = gethostbyname(hostip)) == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &srvInfo, sizeof(srvInfo));
srvInfo.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&srvInfo.sin_addr.s_addr, server->h_length);
srvInfo.sin_port = htons(portno);
if(connect(sockFd,(struct sockaddr *) &srvInfo,sizeof(srvInfo)) < 0)
error("ERROR connecting");
{
bzero(buffer,256);
if((n = read(sockFd,buffer,255)) < 0)
error("ERROR reading from socket");
printf("Socket read = %s\n", buffer);
}
close(sockFd);
}
main(int argc, char* argv[])
{
char hostip[50] = {0};
unsigned int portNo= 444;
printf("B. Provide the host name or IP:\n");
scanf("%s",&hostip);
simple_internet_client(hostip, portNo);
return(0);
}
When I run the client(./clientdemo) at some intervals then the client receives whatever string the server sends.
But when I run the client multiple times through some script then the client remains stuck up at read() call and does not receive what the server has sent.
Simply speaking when the client connects to the server at faster rate then the server writes to the socket at same rate.But the client is not able to read the data written on the socket and remains stuck up on the read() call.
What may be the cause of this and why client is not able to read data from socket at same rate as server writes to it?
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).