how to connect client immediately one after the other in tcp socket api program - sockets

server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<poll.h>
#include<unistd.h>
#include<arpa/inet.h>
int main()
{
struct pollfd fdarray[5];
int sfd,port,nsfd,n,clen,ret,i;
char str[100];
struct sockaddr_in sadd,cadd;
memset(str,0,sizeof(str));
sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
printf("sorry unable to open the file");
exit(1);
}
memset(&sadd,0,sizeof(sadd));
sadd.sin_port=htons(9796);
sadd.sin_family=AF_INET;
sadd.sin_addr.s_addr=INADDR_ANY;
if(bind(sfd,(struct sockaddr*) &sadd,sizeof(sadd))<0)
{
printf("earror");
exit(0);
}
listen(sfd,5);
clen=sizeof(cadd);
for(i=0;i<5;i++)
{
nsfd=accept(sfd,(struct sockaddr*)&cadd,&clen);
if(nsfd<0)
{
printf("error accepting client");
exit(1);
}
fdarray[i].fd=nsfd;
fdarray[i].events=POLLIN;
fdarray[i].revents=0;
}
while(1)
{
ret=poll(fdarray,5,-1);
for(i=0;i<5;i++)
{
if(fdarray[i].revents==POLLIN)
{
n=read(fdarray[i].fd,str,100);
if(n<0)
printf("arreo");
printf("message is:%s \n",str);
char *buff="message received";
int j;
for( j=0;j<5;j++)
{
if(j!=i)
n=write(fdarray[j].fd,buff,sizeof(buff));
}
}
}
}
return 0;
}
i wrote a program for chat server i.e for example if four client are connected if one of the client send a message then all the other clients should get the message except the sending this process should be done by server i.e client should send to server and server should to all the others now in my code the server waits until all the five clients gets connected what should i do inorder to connect all the clients immediately one after the other not waiting till all are connected
client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<poll.h>
#include<unistd.h>
int main(int argc,char* argv[])
{
int sfd,i;
char msg[1024];
char blanmsg[1024];
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
sfd=socket(AF_INET,SOCK_STREAM,0);
saddr.sin_family=AF_INET;
inet_pton(AF_INET,"127,0.0.1",&saddr.sin_addr);
saddr.sin_port=htons(9796);
connect(sfd,(struct sockaddr*)&saddr,sizeof(saddr));
for(i=0;i<5;i++)
{
fgets(msg,1024,stdin);
send(sfd,msg,strlen(msg),0);
recv(sfd,blanmsg,sizeof(blanmsg),0);
printf("%s",blanmsg);
fflush(stdout);
}
exit(0);
}

If I understand the question correctly: You want to serve already connected clients while some clients are not yet connected.
You can do that by moving client accept()ing into the while(1) loop.
To do that, you must add the server socket to fdarray, and add client sockets to the fdarray when new clients are accepted.
Here is quite similar example: Single thread echo server implemented by using poll()

Related

Unable to send publish messages from esp8266 to Raspberry (Broker) using MQTT. Getting Socket Error <Random Device Id>, Disconnecting

I am trying to send and receive a messages from Raspberry Pi (Broker) to Arduino-ESP8266 (client) using MQTT. What I am trying to achieve is pretty basic for now. The broker sends a start command and the client on receving the message should send back a random number. I am able to read the message sent by the broker but the messages from the client are never sent. Here is the code that I am using
#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(19, 18); //RX, TX
#endif
#define MQTT_KEEPALIVE 10
#include <PubSubClient.h>
IPAddress server(192, 168, 0, 105);
char ssid[] = "user1956";
char password[] = "******";
int status = WL_IDLE_STATUS; //wifi radio's status
//MQTT
//const char* mqtt_topic = "Rpi_Master";
const char* mqtt_username = "pi";
const char* mqtt_password = "********";
//client Id
const char* clientID = "A_2";
//Variables for numbers
long randNumber1;
String rn1;
char rn1_char[50];
WiFiEspClient wifiClient;
PubSubClient client(wifiClient); //1883 is the listener port for the broker
void setup() {
// Initilize serial for debugging
Serial.begin(115200);
//initilize serial for ESP module
Serial1.begin(115200);
//initilize the ESP module
WiFi.init(&Serial1);
if (WiFi.status() == WL_NO_SHIELD)
{
Serial.println("WiFi shield not present");
while (true);
}
while (status != WL_CONNECTED)
{
Serial.print("Attempting to connect to WPA SSID : ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
}
Serial.println("You are connected to the network");
client.setServer(server, 1883);
client.setCallback(callback);
//Allow the hardware to sort itself
delay(1500);
randomSeed(50);
}
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Message Received: [");
Serial.print(topic);
Serial.println("]");
Serial.print("Message is:");
String message = (char *)payload;
Serial.println(message);
else if (!strncmp((char *)payload, "B1", length)) //Start code can be changed to any string value in place of 1
{
client.publish("Ad_B", "OK");
generateRandomData();
}
else if (!strncmp((char *)payload, "B2", length)) //Start code can be changed to any string value in place of 1
{
client.publish("Ad_B", "OK");
generateRandomData();
}
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
delay(1000);
}
void reconnect()
{
while (!client.connected())
{
Serial.print("Attempting MQTT Connection...");
//Attempt to Connect
if (client.connect(clientID, mqtt_username, mqtt_password))
{
Serial.println("connected");
//Once connected publish an announcement
client.publish("Ad_B", "Ready");
//and resubscribe
client.subscribe("Rpi_Master"); //This name can be changed
}
else
{
Serial.print("failed, rc = ");
Serial.print(client.state());
Serial.println("Trying again in 5 seconds");
//Wait for 5 seconds before retrying
delay(5000);
}
}
}
void generateRandomData(){
randNumber1 = random(0,0); //(14000,15000)
//Serial.println(randNumber1); // print a random number from 0to 299
rn1 = String(randNumber1);
rn1.toCharArray(rn1_char, rn1.length() + 1);
client.publish("LC_B_1", rn1_char);
client.publish("Ad_B", "End");
}
This is the output of the serial monitor that I am receiving:
07:45:42.016 -> [WiFiEsp] Initializing ESP module
07:45:45.430 -> [WiFiEsp] Initilization successful - 1.5.4
07:45:45.430 -> Attempting to connect to WPA SSID : No Free Wifi
07:45:50.464 -> [WiFiEsp] Connected to No Free Wifi
07:45:50.464 -> You are connected to the network
07:45:51.940 -> Attempting MQTT Connection...[WiFiEsp] Connecting to 192.168.0.105
07:45:52.084 -> connected
07:46:31.926 -> Message Received: [Rpi_Master]
07:46:31.926 -> Message is:B2ter
07:46:37.438 -> [WiFiEsp] TIMEOUT: 20
08:20:58.967 -> [WiFiEsp] >>> TIMEOUT >>>
The client is unable to publish any messages. The mosquitto log shows PINGREQ and RINGRESP to a random id and client.publish stops with the following message in the log - Socket Error on Client <Some Random Client Id>, Disconnecting. Attached the screenshot of the log. Is there any way to know what the unknown client is? Please help me to sort this issue. Thanks.
You generateRandom() function blocks (15 seconds) for longer than the keep alive (10 seconds) timeout and this will block the client.loop() function so it will not be able to send keep alive packets.

Epoll events(EPOLLLT) only triggered once on udp socket

From online resource, they said that if epoll listening on file descriptors using default mode(level trigger), when the fd(file descriptor) is ready to read and the buffer data associated with fd not fully consumed, epoll will continue to trigger until all data is consumed, however, when I test with epoll(LT mode) listening on udp socket, when multiple characters comes epoll only trigger once.
the process like below:
step 1: create epoll, udp socket fd, then make epoll listening on socket for write event.
step 2: send multiple characters("abc") to the udp socket
step 3: each time epoll triggered, then read 1 character from the udp socket.
I am expecting that epoll trigger three times as udp socket receive 3 characters, but the result is epoll only trigger once.
here is my code:
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define BUFFER_SIZE 512
#define log(fmt, arg...) printf(""fmt, ##arg)
void main(){
int fd1,efd, fds, i, fd;
int ret, addr_len;
struct epoll_event g_event;
struct epoll_event *epoll_events_ptr;
char buffer[BUFFER_SIZE] = {0};
struct sockaddr_in addr1;
fd1 = socket(AF_INET, SOCK_DGRAM, 0);
if (fd1 == -1) {
log("create socket fail \r\n");
return ;
}
addr1.sin_family = AF_INET;
addr1.sin_addr.s_addr = INADDR_ANY;
addr1.sin_port = htons(3500);
addr_len = sizeof(struct sockaddr_in);
if (0 != bind(fd1, (struct sockaddr *)&addr1, sizeof(struct sockaddr_in))) {
log("bind local listening addr fail,errno : %d \r\n", errno);
goto err;
}
efd = epoll_create1(0);
if (efd == -1) {
log("create epoll fail \r\n");
goto err;
}
log("create epoll instance success \r\n");
epoll_events_ptr = (struct epoll_event *)calloc(2, sizeof(struct epoll_event));
if (epoll_events_ptr == NULL) {
log("calloc fail \r\n");
goto err;
}
g_event.data.fd = fd1;
g_event.events = EPOLLIN;
epoll_ctl(efd, EPOLL_CTL_ADD, fd1, &g_event);
while(1) {
fds = epoll_wait(efd, epoll_events_ptr, 2, -1);
for (i = 0; i<fds; i++)
{
if (epoll_events_ptr[i].events & EPOLLIN)
{
ret = recv(fd1, buffer, 1, MSG_DONTWAIT);
if(ret != -1)
log("recv msg : %s \n", buffer);
}
memset(buffer, 0, BUFFER_SIZE);
}
}
err:
close(fd1);
if(epoll_events_ptr)
free(epoll_events_ptr);
return ;
}
enter image description here
You are treating UDP as though it was a streaming protocol, i.e. TCP. It isn't. It is a datagram protocol. If you read a UDP datagram into a buffer that is too small to receive it, the remainder of the datagram is discarded. Not left in the buffer for next time.
Reading one character at a time is therefore pointless in UDP, not to mention extremely inefficient in any protocol.
NB You don't need the memset(), and this:
log("recv msg : %s \n", buffer);
is invalid. It should be:
log("recv msg : %.*s \n", ret, buffer);
You can't assume the received data is null-terminated.

systemd-activate socket activation for UDP daemons

I like using systemd-activate(8) for testing socket-activated daemons during development,
however, it seems it only listens for TCP connections:
% /usr/lib/systemd/systemd-activate -l 5700 ./prog
Listening on [::]:5700 as 3.
% netstat -nl |grep 5700
tcp6 0 0 :::5700 :::* LISTEN
I am using a program that handles datagrams (UDP). How can I make systemd-activate listen on a UDP port? Or is there a
simple way to do this using other tools, without going to the trouble of crafting and installing a systemd unit file?
This was recently added to systemd-activate: https://github.com/systemd/systemd/pull/2411, and will be part of systemd-229 when it is released.
I'm not sure that there is a way to do it with systemd-activate.
You may want to employ some .service unit file and a .socket unit file with dependencies. In a .socket unit you will describe ListenDatagram= option. See here for more details.
I ended up writing a simple C program to do this; code below (public domain).
The usage is:
./a.out <port-number> <prog> [<arg1> ...]
The program opens a UDP socket on <port-number>, sets the environment variables that systemd socket-activated daemons expect, then executes <prog> with whatever arguments follow.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("no port specified\n");
return -1;
}
if (argc < 3) {
printf("no program specified\n");
return -1;
}
uint16_t port = htons((uint16_t) strtoul(argv[1], NULL, 10));
if (port == 0 || errno) {
printf("failed to parse port: %s\n", argv[1]);
return -1;
}
/* create datagram socket */
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("failed to open socket; errno: %d\n", errno);
return -1;
}
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = port;
sa.sin_addr.s_addr = INADDR_ANY;
/* bind socket to port */
int r = bind(fd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
if (r < 0) {
printf("bind failed; errno: %d\n", errno);
return -1;
}
/* execute subprocess */
setenv("LISTEN_FDS", "1", 0);
execvp(argv[2], argv + 2);
}

Why is Windows 7 firewall preventing PASV FTP connections?

I was trying to get CFtpServer's first example program running on a Windows 7 Pro, x64 system. After much beating around the bush and not believing what I was seeing, I got the problem down to the following simple program:
#include <iostream>
using namespace std;
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#define die(code) { cerr << "die at " << __FILE__ << " " << __LINE__ << " "; exit(code); }
int main(int argc, char **argv)
{
short port = 21;
if (argc == 2) {
port = atoi(argv[1]);
}
WSADATA WSAData;
if ( WSAStartup( MAKEWORD(2, 2), &WSAData) != 0)
die(1);
SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//!!! proto 0 in ftpdmin!
if (ls == INVALID_SOCKET) die(1);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons( port );
if (bind( ls, (struct sockaddr *) &sin, sizeof( struct sockaddr_in ) )
== SOCKET_ERROR) die(2);
if (listen( ls, 1 ) == SOCKET_ERROR ) //!!! backlog 1 in ftpdmin!
die(3);
// wait for connect, transmit till error
SOCKET ts;
for( ;; ) {
ts = accept( ls, NULL, NULL );
if (ts == INVALID_SOCKET) die(5);
// now write some things to that socket.
int i=0;
for(;;) {
char buf[256];
sprintf(buf, "%d Testing...\r\n",i+224);
if (send(ts, buf, strlen(buf), 0) < 0) {
DWORD err = WSAGetLastError();
cerr << "send failed with " << err << endl;
break;
}
Sleep(1000);
i = (i+1)%10;
}
Sleep(1000);
closesocket(ts);
}
}
This program opens the specified socket, listens on it for connections. When it gets a connection, it proceeds to write strings that bear a passing resemblance to the string an FTP server might use to respond to the PASV command. It will keep transmitting strings, once a second, until something goes wrong.
On my system, connecting to this 'server' using the nc.exe command, I see a few strings, then the socket will close (the error printed by the 'server' is 10053).
If I disabled the Windows firewall, I see strings as long as I care to leave the nc command running.
I've seen two different variations, and I don't know what causes the difference: Sometimes it would stop when it transmitted the string '227 ', later it started dying on '229 '. It's giving every appearance of being sensitive to the text being sent.
After 3 days of beating my head on this one, I have an answer: Window KB2754804. It's a bug, known to MS since somewhere in 2011. There is a Hotfix in the referenced Knowledge base article, but it doesn't seem to work for my tests, so I had to take the alternative route of disabling the Stateful FTP firewall.
I finally got to the KB article, from this SO entry.

how to bind a UDP socket to a range of port

I want to write a kernel thread for an application that will read all UDP packets. I am facing problem in binding as these packet can arrive in range of ports (say 5001 to 5005).
How to do this.
Any pointer/link will be helpful.
You can't bind a socket to more than one port, do as 0verbose suggested in a comment and use one socket per port
Besides opening multiple sockets, you need to use select()/poll() to listen to all sockets at once.
If you are programming in C/C++ under Linux, here is a pseudo-code in C:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
...
int main()
{
fd_set afds;
fd_set rfds;
int maxfd = -1;
int fd, ret;
/* initialize fdsets */
FD_ZERO(&afds);
/* create a socket per port */
foreach (port p) {
fd = create_udp_socket(p); /* also bind to port p */
if (fd < 0) error_exit("error: socket()\n");
FD_SET(fd, &afds);
if (fd > maxfd) maxfd = fd;
}
while (1) {
memcpy(&rfds, &afds, sizeof(rfds));
/* wait for a packet from any port */
ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
if (ret < 0) error_exit("error: select()\n");
/* which socket that i received the packet */
for (fd=0; fd<=maxfd; ++fd)
if (FD_ISSET(fd, &rfds))
process_packet(fd); /* read the packet from socket fd */
}
}
Hope this code will help you