I create chat with clients and server. But the client can't connect to the server. Please tell me what is wrong?
Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define BUFOR 512
int main(int argc, char *argv[])
{
int fd, serverLength, cLength;
struct sockaddr_in serverAddr, c_addr[2], clientAddr;
cLength = sizeof(clientAddr);
char buf[BUFOR];
int clients = 0;
int c_port[2];
if(argc != 2)
{
printf(" portu");
exit(1);
}
uint16_t port = atoi( argv[ 1 ] );
if ((fd = socket(AF_INET, SOCK_DGRAM, 0))==-1)
{
perror("Blad socket");
exit(1);
}
bzero((char*) &serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(port);
serverLength = sizeof(serverAddr);
if (bind(fd, (struct sockaddr* ) &serverAddr, serverLength)==-1)
{
perror("Blad bind");
exit(1);
}
for(;;)
{
printf("Receiving...\n");
if (recvfrom(fd, buf, BUFOR, 0, (struct sockaddr*)&clientAddr, &cLength)==-1)
{
perror("Blad recvfrom");
exit(1);
}
if (clients==0)
{
c_addr[0] = clientAddr;
c_port[0] = ntohs(c_addr[0].sin_port);
clients++;
printf("Client 0 was connected. Port: %d\n",c_port[0]);
sendto(fd, "I am only one cleint.", 24, 0, (struct sockaddr*)&clientAddr, cLength);
}else if(clients==1)
{
if (c_port[0]==ntohs(clientAddr.sin_port))
{
sendto(fd, "I am only one client.", 24, 0, (struct sockaddr*)&c_addr[0], sizeof(c_addr[0]));
printf("One cleint\n");
}else
{
c_addr[1] = clientAddr;
c_port[1] = ntohs(c_addr[1].sin_port);
clients++;
printf("Second cleint\n");
sendto(fd, buf, BUFOR, 0, (struct sockaddr*)&c_addr[0], sizeof(c_addr[0]));
}
}else
{
if (c_port[0]==ntohs(clientAddr.sin_port))
{
printf("Sending emssage for client 1\n");
if (sendto(fd, buf, BUFOR, 0, (struct sockaddr*)&c_addr[1], sizeof(c_addr[0]))==-1)
{
clients--;
perror("Error senttoen");
}
}else
{
printf("Sending message for client 0\n");
if (sendto(fd, buf, BUFOR, 0, (struct sockaddr*)&c_addr[0], sizeof(c_addr[1]))==-1)
{
clients--;
perror("Blad senttoen");
}
}
}
}
close(fd);
return 0;
}
Client code
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#define BUFLEN 512
int main(int argc, char *argv[])
{
struct sockaddr_in serv_addr;
int sockfd;
socklen_t slen;
slen=sizeof(serv_addr);
char buf[BUFLEN];
if(argc != 3)
{
printf("Usage : %s <Server-IP>\n",argv[2]);
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
{
perror("Socket Error");
exit(1);
}
uint16_t port = atoi( argv[ 1 ] );
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = inet_addr(argv[2]);
while(1)
{
bzero(buf,BUFLEN);
printf("Attempting to READ to socket %d: ",sockfd);
fflush(stdout);
if(recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, &slen)==-1)
{
perror("Blad bind");
exit(1);
}
printf("The message from the server is: %s \n",buf);
printf("Please enter the message to send: ");
bzero(buf,BUFLEN);
fgets(buf,BUFLEN,stdin);
printf("Attempting to write to socket %d: ",sockfd);
fflush(stdout);
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
{
perror("Blad bind");
exit(1);
}
}
close(sockfd);
return 0;
}
It seems the sendto is blocked by recvfrom, but I don't know how to create it in infinitable loop.
Related
I am trying to make communication between raspberry pi 4 and my ubuntu machine using socket programming. When i run them in same machine it works fine. But when i do it in different machine it shows error saying : no such host. Here is the server.c
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t 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);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
Here is the client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
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);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
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");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
To run the server i use the cmd: ./server 8081 and to run the client i used:
./client raspberrypi 8081
after which the error is showing. when i do the same in laptop it works fine. i checked the hostname is also correct.
no such host means the computer cannot resolve the hostname (raspberrypi) to a IP address (typically using DNS).
Assuming the server is the Rasberry Pi, add the following line to the file /etc/hosts on your client
192.168.0.5 rasberrypi
Replacing 192.168.0.5 with the IP address of your raspberrypi.
I would like to see how much time it takes for connect syscall. I get the code for a simple TCP client. However, the program will wait for the server to respond after connect. How can I make it return right after syscall or using some other ways to time the syscall time?
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]) {
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2) {
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0) {
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("\n Error : Connect Failed \n");
return 1;
}
printf("\nhello\n");
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) {
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF) {
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
However, the program will wait for the server to respond after connect.
Yes, and it does so here:
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) {
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF) {
printf("\n Error : Fputs error\n");
}
}
How can I make it return right after syscall
Err, remove the receive loop above?
i have written the client and server c file to make an echo server program,i wrote it according to the tutorial video, but i can not figure out where i made the mistakes
//this is the client.c
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
int main(void)
{
int sock;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("socket establish fail!");
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(30000);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr))<0)
printf("connect failed");
char sendbuf[1024] = { 0 };
char recvbuf[1024] = { 0 };
while (fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write(sock, sendbuf, sizeof(sendbuf));
read(sock, recvbuf, sizeof(recvbuf));
//fputs(recvbuf, stdout);
printf("%s",recvbuf);
memset(sendbuf, 0, sizeof(sendbuf));
memset(recvbuf, 0, sizeof(recvbuf));
}
close(sock);
return 0;
}
and
//this is the server.c
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
int main(void)
{
int listenfd, conn;
struct sockaddr_in peeraddr;
struct sockaddr_in servaddr;
socklen_t peerlen = sizeof(peeraddr);
char recvbuf[1024];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("socket establish fail!");
memset(&servaddr, 0, sizeof(servaddr));
memset(&recvbuf, 0, sizeof(recvbuf));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(30000);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
printf("Bind fail");
if (listen(listenfd, 5) < 0)
printf("Listen fail");
if (conn= accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen) < 0)
printf("accept fail");
while (1)
{
int ret = read(conn, recvbuf, sizeof(recvbuf));
//fputs(recvbuf,stdout);
printf("%s",recvbuf);
write(conn, recvbuf, ret);
}
close(conn);
close(listenfd);
return 0;
}
i worked for it for several hours but i can not find the answer
please help me!
Hi am trying to implement net link user code and kernel code every thing works fine for unicast (src_addr.nl_groups = 0;). For mulicast, user code bind call always fails for non zero src_addr.nl_groups value. Really am not sure what value to put for multicast and how to proceed further. I checked the usage of netlink_broadcast in kernel source tree, so I put the same group Id value (RTMGRP_LINK) here. For unicast I found good number of help in internet but for multicast I don't think so . So Please help me to proceed further.
Error am getting is:
bind: No such file or directory
./a.out: can't bind socket (3)and err : -1: No such file or directory
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdio.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define NETLINK_TEST 28
#define GROUP_IB 1
#define MAX_PAYLOAD 1024
struct sockaddr_nl src_addr, dst_addr;
struct nlmsghdr *nlh = NULL;
struct msghdr msg;
struct iovec iov;
int sock_fd;
int main(int argc, char ** argv)
{
int err;
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
if (sock_fd<0) {
char s[BUFSIZ];
sprintf( s, "%s: can't assign fd for socket", argv[0] );
perror(s);
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 0; // Unicast
//src_addr.nl_groups = RTMGRP_LINK; /* Multicast, bind call always fails for non zero values */
err = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
perror("bind");
if (err<0) {
char s[BUFSIZ];
sprintf( s, "%s: can't bind socket (%d)and err : %d", argv[0], sock_fd,err );
perror(s);
return -1;
}
memset(&dst_addr, 0, sizeof(dst_addr));
nlh = (struct nlhmsghdr *) malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_name = (void *)&dst_addr;
msg.msg_namelen = sizeof(dst_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("pid : %d\n Waiting for messages from kernel...\n",getpid());
recvmsg(sock_fd, &msg, 0);
printf("Message : %s\n", NLMSG_DATA(nlh));
close(sock_fd);
return 0;
}
Netlink socket binds are sensitive to what USER you are- I've seen them reliably fail if you are not running the program in question as 'root', at least on RedHat 6.
Try running as root 1st, before changing your logic. If you get the same failure as you do in normal operation, then you know it isn't (necessarily) a permissions issue.
The issue is
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
Does you kernel module define the NETLINK_TEST family? your own family might must be supported at kernel module and it should post the message in the proper group using nlmsg_multicast()
RTMGRP_LINK is group defined in NETLINK_ROUTE.
This sample code is example for multicast
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#define MYPROTO NETLINK_USERSOCK
#define MYMGRP 21
int open_netlink(void)
{
int sock;
struct sockaddr_nl addr;
int group = MYMGRP;
sock = socket(AF_NETLINK, SOCK_RAW, MYPROTO);
if (sock < 0) {
printf("sock < 0.\n");
return sock;
}
memset((void *) &addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
/* addr.nl_groups = MYMGRP; */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
printf("bind < 0.\n");
return -1;
}
if (setsockopt(sock, 270, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)) < 0) {
printf("setsockopt < 0\n");
return -1;
}
return sock;
}
void read_event(int sock)
{
struct sockaddr_nl nladdr;
struct msghdr msg;
struct iovec iov;
char buffer[65536];
int ret;
iov.iov_base = (void *) buffer;
iov.iov_len = sizeof(buffer);
msg.msg_name = (void *) &(nladdr);
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Ok, listening.\n");
ret = recvmsg(sock, &msg, 0);
if (ret < 0)
printf("ret < 0.\n");
else
printf("Received message payload: %s\n", NLMSG_DATA((struct nlmsghdr *) &buffer));
}
int main(int argc, char *argv[])
{
int nls;
nls = open_netlink();
if (nls < 0)
return nls;
while (1)
read_event(nls);
return 0;
}
kernel module:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netlink.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#define MYPROTO NETLINK_USERSOCK
#define MYGRP 21
static struct sock *nl_sk = NULL;
static void send_to_user(void)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
char *msg = "Hello from kernel";
int msg_size = strlen(msg) + 1;
int res;
pr_info("Creating skb.\n");
skb = nlmsg_new(NLMSG_ALIGN(msg_size + 1), GFP_KERNEL);
if (!skb) {
pr_err("Allocation failure.\n");
return;
}
nlh = nlmsg_put(skb, 0, 1, NLMSG_DONE, msg_size + 1, 0);
strcpy(nlmsg_data(nlh), msg);
pr_info("Sending skb.\n");
res = nlmsg_multicast(nl_sk, skb, 0, MYGRP, GFP_KERNEL);
if (res < 0)
pr_info("nlmsg_multicast() error: %d\n", res);
else
pr_info("Success.\n");
}
static int __init hello_init(void)
{
pr_info("Inserting hello module.\n");
nl_sk = netlink_kernel_create(&init_net, MYPROTO, NULL);
if (!nl_sk) {
pr_err("Error creating socket.\n");
return -10;
}
send_to_user();
netlink_kernel_release(nl_sk);
return 0;
}
static void __exit hello_exit(void)
{
pr_info("Exiting hello module.\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
I have the following code with connects to Redis running locally on port 6379. The problem is that can't read any output, the reader thread just blocks on recvfrom(). Everything works fine with an echo server for example, but not with Redis.
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
struct sockaddr_in servAddr;
int sock;
/* Reader loop */
void *readerf(void *n) {
char buffer[128];
int bytesRcvd;
while((bytesRcvd = recvfrom(sock, buffer, 127, 0, NULL, 0)) > 0) {
printf("[%s]",buffer);
}
}
char *getk = "GET key\n";
char *setk = "SET key \"test\"\n";
void sendd(char *str) {
if (send(sock, str, strlen(str), 0) != strlen(str))
perror("Send error");
send(sock, "\0", 1, 0);
//printf("sent: [%s]",str);
}
int main(int argc, char *argv[]) {
int i = 1;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
return 1;
/* Construct the server address structure */
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family */
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); /* Server IP address */
servAddr.sin_port = htons(6379); /* Server port */
if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr))<0)
perror("Could not connect");
sendd(getk);
sendd(setk);
sendd(getk);
pthread_t reader;
pthread_create(&reader, NULL, readerf, &i);
sleep(5);
close(sock);
return 0;
}
It seems like you are not properly implementing Redis' protocol: http://redis.io/topics/protocol
If you are seriously coding a client, and not just investigating/having fun consider hiredis: https://github.com/antirez/hiredis/