Sockets, client server communication using SOCK_DGRAM, epoll - c

I'm trying to write a program with AF_INET, SOCK_DGRAM, where client connects to server sends it message "First message" and then the server responds to client with "Second message".
Q1: In my code server receives "First message", however client doesn't get server response "Second message", why?
Q2: In client I connect to server using msg_addr.sin_addr.s_addr =INADDR_ANY; I would like to change it for something like: msg_addr.sin_addr.s_addr =htonl(inet_addr("172.126.154.12")); where ip "172.126.154.12"is server ip;
server.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
typedef struct{
int type;
int arg1;
int arg2;
int result;
char name[50];
}Msg;
#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}
int web_fd, epoll;
struct sockaddr_in server_addr;
Msg msg;
struct sockaddr msg_addr;
int main(int argc, char *argv[]){
if((web_fd = socket(AF_INET, SOCK_DGRAM,0)) == -1) FAILURE_EXIT("Failed to create communication endpoint web_fd\n");
int yes=1;
if (setsockopt(web_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) == -1) FAILURE_EXIT("setsockopt web_fd\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9992);
server_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(web_fd,(const struct sockaddr*) &server_addr,sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));
epoll = epoll_create1(0);
if(epoll == -1) FAILURE_EXIT("Failed to create new epoll instance: %s\n",strerror(errno));
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = web_fd;
if(epoll_ctl(epoll,EPOLL_CTL_ADD,web_fd,&event)== -1) FAILURE_EXIT("Failed to register web_fd file descriptor on epoll instance: %s\n",strerror(errno));
printf("Server starts loop.\n");
while(1){
struct epoll_event event;
WRITE("Waiting for client message...\n");
int nfd = epoll_wait(epoll,&event,1,-1);
if(event.data.fd == web_fd){
recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr,0);
WRITE("Received message from client %s\n",msg.name);
strcpy(msg.name,"Second message");
sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, (socklen_t) sizeof(msg_addr) );
}else{
WRITE("Unknown descriptor\n");
}
}
}
client.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
typedef struct{
int type;
int arg1;
int arg2;
int result;
char name[50];
}Msg;
#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}
int socket_fd;
struct sockaddr_in msg_addr;
Msg msg;
int main(int argc, char *argv[]){
struct sockaddr_in msg_addr;
msg_addr.sin_family = AF_INET;
msg_addr.sin_addr.s_addr =INADDR_ANY;
msg_addr.sin_port = htons(9992);
socket_fd = socket(AF_INET, SOCK_DGRAM,0);
if(socket_fd == -1) FAILURE_EXIT("Failed to create client socket\n");
if(connect(socket_fd, (const struct sockaddr*) &msg_addr, sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));
strcpy(msg.name,"First message ");
sendto(socket_fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr,(socklen_t) sizeof(Msg));
WRITE("Waiting..\n");
recvfrom(socket_fd,&msg,sizeof(Msg),0 ,0,0);
WRITE("f %s\n",msg.name);
WRITE("I registered\n");
sleep(400);
}

In server code change recvfrom() call as this
socklen_t addrsize;
recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr, &addrsize);
and change subsequent sendto() call as this
sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, addrsize);

Related

C Socket, server and client. connect error: "No route to Host"

I've written the client code and the server, however, there is a problem with connect: "No route to host". It is strange because clients and servers operate in a different network. Also, if I ping [my ip] tells me timeout, if I telnet [my ip] tells me error. Can you advise me how to solve this problem? I opened port 2222 from the router but it still does not seem to work.
Sorry for my English
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#define ADDRESS "[IP]"
#define PORT 2222
int main()
{
int sockid;
struct sockaddr_in c_address;
printf("[CLIENT] Eseguito.\n");
c_address.sin_family = AF_INET;
c_address.sin_addr.s_addr = inet_addr(ADDRESS);
c_address.sin_port = htons(PORT);
sockid = socket(AF_INET, SOCK_STREAM, 0);
int sock_conn;
sock_conn = connect(sockid, (struct sockaddr *)&c_address, sizeof(c_address));
if(sock_conn == -1)
{
perror("Connect client");
exit(EXIT_FAILURE);
}
while(1)
{
char text[128];
printf("[CLIENT] Scrivi qualcosa: ");
fgets(text, 128, stdin);
write(sockid, text, 128);
read(sockid, text, 128);
printf("[CLIENT] Testo ricevuto: %s.\n", text);
}
}
Server code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#define PORT 2222
void toggleCharacter(char *str);
int main()
{
int sockid;
struct sockaddr_in s_address;
printf("[SERVER] Eseguito.\n");
s_address.sin_family = AF_INET;
s_address.sin_addr.s_addr = htonl(INADDR_ANY);
s_address.sin_port = htons(PORT);
sockid = socket(AF_INET, SOCK_STREAM, 0);
if(bind(sockid, (struct sockaddr *)&s_address, sizeof(s_address)) == -1)
{
perror("Bind server");
exit(EXIT_FAILURE);
}
if(listen(sockid, 5) == -1)
{
perror("Listen server");
exit(EXIT_FAILURE);
}
int connection_socket;
connection_socket = accept(sockid, NULL, 0);
if(connection_socket == -1)
{
perror("Accept server");
exit(EXIT_FAILURE);
}
char text[128];
while(1)
{
read(connection_socket, text, 128);
printf("[SERVER] Messaggio ricevuto: %s.\n", text);
printf("[SERVER] Scrivi qualcosa: ");
fgets(text, 128, stdin);
write(connection_socket, text, 128);
}
close(connection_socket);
}

when does poll() return POLLERR

server.c -> always recv client data(use poll() to confirm whether an error occurred)
client.c -> always send data to server
I exec server.c and client.c ,then i try to kill client.c process.
But the POLLERR flag never be set.
The man page only say
POLLERR Error condition (output only)
When does Poll() return POLLERR?
What did I miss?
Thanks.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
int main()
{
int rc = 0;
char str[100];
char test[5];
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
struct pollfd fds[200];
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(22000);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
fds[0].fd = comm_fd;
fds[0].events = POLLIN | POLLOUT | POLLERR | POLLHUP;
printf("start\n");
while(1) {
rc = poll(fds,1,1000);
if (rc < 0)
printf("failed\n");
else if(rc==0)
printf("timeout\n");
else {
if (fds[0].revents & POLLERR){
printf("Error!!\n");
}
if(fds[0].revents & POLLHUP){
printf("handup!!\n");
break;
}
if (fds[0].revents & POLLIN){
int bl = recv(comm_fd,test,4,0);
printf("recv:%s %d\n",test,bl);
}
}
sleep(1);
}
return 0;
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char **argv)
{
int sockfd,n;
char sendline[100];
char recvline[100];
struct sockaddr_in servaddr;
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof servaddr);
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(22000);
inet_pton(AF_INET,"127.0.0.1",&(servaddr.sin_addr));
connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
while(1){
send(sockfd,"test",4,0);
sleep(5);
}
close(sockfd);
return 0;
}
It's implementation dependent. Most applications just treat POLLERR the same as normal readiness, allowing the subsequent operation to fail.

how get socket port number from an accept call (C UNIX)

i've done a simple client/server program where the server wait for an external connection and return the connection-socket if the port number of the client is in the range of [1025-2048] otherwise return -1. The problem is that when i get the port number by the client adress (which should be stored in the sockaddr structure) it says me that the client port number is zero, but in the client program i've set the client portnumber to 1999.
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int function(int fd_socket) {
int fd_socket_acc;
int len;
int port;
struct sockaddr_in client_addr;
puts("WAITING FOR CLIENT...");
fd_socket_acc = accept(fd_socket, (struct sockaddr*)&client_addr, &len);
puts("CONNECTION DONE.");
port = ntohs (client_addr.sin_port);
printf("client port number: %d \n", port);
if (port >= 1024 && port <= 2048) {
close (fd_socket_acc);
return fd_socket_acc;
}
else {
close(fd_socket_acc);
return -1;
}
}
int main(int argc, char *argv[]) {
int fd_socket;
struct sockaddr_in local_addr;
fd_socket = socket(AF_INET, SOCK_STREAM, 0);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(1887);
local_addr.sin_addr.s_addr = INADDR_ANY;
bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));
listen(fd_socket, 3);
function(fd_socket);
//close(fd_socket);
}
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int main(int argc, char *argv[]) {
int fd_socket;
struct sockaddr_in local_addr;
struct sockaddr_in server_addr;
struct hostent *hp;
fd_socket = socket(AF_INET, SOCK_STREAM, 0);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(1999);
local_addr.sin_addr.s_addr = INADDR_ANY;
bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1887);
//hostname is "ubuntu"
hp = gethostbyname("ubuntu");
bcopy(hp->h_addr, &server_addr.sin_addr, 4);
printf("%d \n", ntohs(local_addr.sin_port));
connect(fd_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
wait(2);
close(fd_socket);
}
If i get the port number in client with a printf("%d", ntohs(local_addr.sin_port)) it stamps correctly 1999, but if i get the port number of client in server with printf("%d", ntohs(client_addr.sin_port)) it stamps 0. Why?
thanks in advance!
In order to obtain the client port number in client_addr through accept you have to tell accept how big that buffer is by setting
socklen_t len = sizeof(client_addr);
You can alternatively retrieve it by calling afterwards
len = sizeof(client_addr);
getpeername(fd_socket_acc, (struct sockaddr*)&client_addr, &len);
Maybe because you do not set the variable len to anything, and I suspect that your compiler sets it to 0.
What happens is that you try to accept with an undefined len size.
Adding len=sizeof( struct sockaddr_in ); before making a call to accept would help to fill the passed client_addr correctly.

Socket programming in C using http post

Want to do client-server programming using c in windows7, it should send string to server using http POST method. The paramater in POST method should include the ip-address etc:
I got this code from http://souptonuts.sourceforge.net/code/http_post.c.html and changed it for running it on windows, but still 1 error is coming:
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <netdb.h>
#include <assert.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define MAXSUB 200
#define LISTENQ 1024
extern int h_errno;
ssize_t process_http(int sockfd, char *host, char *page, char *poststr)
{
char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
ssize_t n;
snprintf(sendline, MAXSUB,
"POST %s HTTP/1.0\r\n"
"Host: %s\r\n"
"Content-type: application/x-www-form-urlencoded\r\n"
"Content-length: %d\r\n\r\n"
"%s", page, host, strlen(poststr), poststr);
write(sockfd, sendline, strlen(sendline));
while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = '\0';
printf("%s", recvline);
}
return n;
}
int main(void)
{
int sockfd;
struct sockaddr_in servaddr;
char **pptr;
//********** You can change. Puy any values here *******
char *hname = "souptonuts.sourceforge.net";
char *page = "/chirico/test.php";
char *poststr = "mode=login&user=test&password=test\r\n";
//*******************************************************
char str[50];
struct hostent *hptr;
if ((hptr = gethostbyname(hname)) == NULL) {
fprintf(stderr, " gethostbyname error for host: %s: %s",
hname, hstrerror(h_errno));
exit(1);
}
printf("hostname: %s\n", hptr->h_name);
if (hptr->h_addrtype == AF_INET
&& (pptr = hptr->h_addr_list) != NULL) {
printf("address: %s\n",
inet_ntop(hptr->h_addrtype, *pptr, str,
sizeof(str)));
} else {
fprintf(stderr, "Error call inet_ntop \n");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// bzero(&servaddr, sizeof(servaddr));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(80);
inet_pton(AF_INET, str, &servaddr.sin_addr);
connect(sockfd, (SA *) & servaddr, sizeof(servaddr));
process_http(sockfd, hname, page, poststr);
close(sockfd);
exit(0);
}
The error which is coming on MinGW compiler is:
httppost.c:33:12: error: conflicting types for 'WSAGetLastError'
In file included from httppost.c:5:0:
c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/winsock2.h:594:32: n
e: previous declaration of 'WSAGetLastError' was here
The code you've got is under linux based systems, but in MinGW (Windows) unfortunately the identifier h_errno is taken before.
The problem is this line
extern int h_errno;
it's defined previously in windows header files, then you can not use it:
#define h_errno WSAGetLastError()
Just use another identifier instead of h_errno, or even just remove that line!
Maybe you should try the wininet library.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa383630(v=vs.85).aspx

access data from server udp

I have a problem, I have a client server udp, in server side I need to access data from client side to control movement of the robot. For the experiment I use to print "oke" if the value of the data is 1.
here the code program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MYPORT 4950
#define MAXBUFLEN 100
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
char dt[30];
char buf[MAXBUFLEN];
int main()
{
printf("‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐\n");
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket");
exit(1); }
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero),'\0',8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1){
perror("bind");
exit(1); }
while(1){
addr_len = sizeof(struct sockaddr);
if((numbytes=recvfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,&addr_len))==-1)
{
perror("recvfrom");
exit(1);}
buf[numbytes]='\0';
printf("%s : \"%s\"\n", inet_ntoa(their_addr.sin_addr), buf);
if (buf[0]==1)
{ printf("oke\n");}
printf("Me : ");
scanf("%s", dt);
if((numbytes=sendto(sockfd,dt,strlen(dt),0,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)))==-1)
{
perror("sendto");
exit(1);
}
}
close(sockfd);
return 0;
}
when I put "1" in client side the result is:
‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐
130.130.66.76 : "1"
Me :
even in the program there are:
if (buf[0]==1)
{ printf("oke\n");}
why the program cannot access to inside of if?
Try if (buf[0]=='1')
Number characters map to different ASCII values than their number, so, for example, '1'==49.

Resources