I am running the example sketches for a server and client:
Client:
/**
* Shared Drawing Canvas (Client)
* by Alexander R. Galloway.
*
* The Processing Client class is instantiated by specifying a remote
* address and port number to which the socket connection should be made.
* Once the connection is made, the client may read (or write) data to the server.
* Before running this program, start the Shared Drawing Canvas (Server) program.
*/
import processing.net.*;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
// Connect to the server's IP address and port
c = new Client(this, "127.0.0.1", 8080); // Replace with your server's IP and port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
c.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from server
if (c.available() > 0) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}
Server:
/**
* Shared Drawing Canvas (Server)
* by Alexander R. Galloway.
*
* A server that shares a drawing canvas between two computers.
* In order to open a socket connection, a server must select a
* port on which to listen for incoming clients and through which
* to communicate. Once the socket is established, a client may
* connect to the server and send or receive commands and data.
* Get this program running and then start the Shared Drawing
* Canvas (Client) program so see how they interact.
*/
import processing.net.*;
Server s;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
s = new Server(this, 8080); // Start a simple server on a port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
s.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from client
c = s.available();
if (c != null) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}
Now I think I should be able to inspect what the server is doing when I go to http://127.0.0.1:8080/. Unfortunately my browser seems to be unable to establish a connection with the server. Have I done something wrong and can it be fixed or are my expectations unrealistic?
The server and the client communicate via a network socket. They pass data in a format that is not understandable for your browser. The way to get the example to run is to launch the server first and the client second (you need to start the Processing environment two times). Now you should be able to draw lines on one side and see them being copied on the other side.
If you want to inspect what the server and client are doing, you can add println statements to the code.
The example code that you are using can be found here on GitHub:
https://github.com/processing/processing/tree/master/java/libraries/net/examples
Related
I have a master device and ESP32 acting as a slave, communicating directly over UART with RX/TX cables. I've created a task that checks the serial stream every 50 ms and parses the data. My problem is that the serial stream freezes up, seemingly randomly, and only restarts if the master or the slave are restarted.
The task looks as such:
void TaskListen_UART(void *pvParameters)
{
while (true)
{
if (readSerialIn())
{
slaveRunCommand(serialData.command); // Execute received commmand
}
vTaskDelay(50 / portTICK_PERIOD_MS);
}
}
It checks the serial stream through readSerialIn() which looks like the following:
bool readSerialIn()
{
if (UART.available() > 0) // Check if the Serial port received data
{
serialData.clearStruct(); // Clear previously saved data
if (UART.find(0x2A)) // Find "*" // Find starting delimiter
{
serialData.length = UART.read(); // Read length
if (serialData.length > BYTE_BUFFER_LEN)
{
writeSerialNACK(); // Write NACK if length seems incorrect
return false;
}
Serial.printf(("Message length: %d\n"), serialData.length);
serialData.checksum = UART.read(); // Read Checksum
Serial.printf(("Checksum: %d\n"), serialData.checksum);
if (parseBuffer(serialData.length)) // Parse the data
{
if (serialData.checkSum()) // If the checksum passes
{
serialData.assignBuffer(); // Save the parsed data to the global buffer
return true;
}
else
{
writeSerialNACK();
return false;
}
}
else
false;
}
else
return false;
}
}
The parseBuffer() function is what actually reads the stream and parses it into their according values on the slave. I tried to write it in the most fail-safe fashion, but it still hasn't cleared up my issue.
bool parseBuffer(uint8_t bufferLength)
{
uint8_t bufferPos = 0;
bool uartDetectFlag = false;
while (UART.available() > 0)
{
uartDetectFlag = true;
if (bufferPos < bufferLength)
{
serialData.serialBuffer[bufferPos] = UART.read();
}
bufferPos++;
}
if (uartDetectFlag)
return true;
else
return false;
}
At first I was suspicious that the ESP was trying to access a block in memory that doesn't exist. I noticed however that it doesn't reset itself like it normally would if that were the case, and I tried writing parseBuffer in a non-blocking manner. I also tried increasing the task delay to 100 ms, which reduced the frequency of the blocking but did not suffice in terms of speed. Regardless, it freezes up and (I think) it's caused by a large flow of data through the serial stream.
I am trying to implement a TCP server using C in Linux. I want this server to accept incoming data forever from multiple clients and at the same time send some data back to each connected client in every 3 seconds.
My problem is I don't know how to properly do send() in a different process than the one handling the client.
What I am doing is at the beginning of the program do a fork() and do
while (1) {
sleep(3);
// compute and `send()` data to each connected peers
}
in child process, do
sock = create_socket();
while (1) {
client_sock = accept_connection(sock);
if (fork() == 0) {
close(sock);
handle_client(client_sock);
exit(0);
}
close(client_sock);
// clean up zombies
}
in parent process. handle_client() is simply recv() data in a infinite loop. Because send() and recv() are executed in different processes, I couldn't use the socket file descriptors to send() in parent process. What do I need to do in the parent process to do the send()?
You have three levels of processes, a parent, a child, and many grandchildren. Get rid of these levels, and do not fork at all; instead using an event-driven model in a single process.
In rough pseudo-code (translate to your preferred language):
listening_fd = create_socket();
EventQueueOfSomeKind q; // kqueue()-style
q.add_or_update_event(listening_fd, EVFILT_READ, EV_ENABLE);
q.add_or_update_event(3, EVFILT_TIMER, EV_ENABLE, NOTE_SECONDS);
FDToContextMapOfSomeKind context_map;
EventVector event_vector; // vector of kevent-like things
while (1) {
q.wait_for_events(&event_vector); // kevent()-style
foreach e <- event_vector {
switch (e.type) {
case EVFILT_READ:
if (listening_fd == e.fd) {
client_sock = accept_connection(e.fd, SOCK_NONBLOCK);
q.add_or_update_event(client_sock, EVFILT_READ, EV_ENABLE);
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_DISABLE);
context_map.add_new_context(client_socket);
} else {
// Must be one of the client sockets
if (e.flags & EV_EOF) {
context_map.remove_context(e.fd);
q.remove_event(e.fd, EVFILT_READ);
q.remove_event(e.fd, EVFILT_WRITE);
close(e.fd);
} else {
recv(e.fd, buffer);
handle_client_input(&context_map[e.fd], buffer);
}
}
break;
case EVFILT_WRITE:
if (has_queued_output(context_map[e.fd])) {
send(e.fd, pull_queued_output(&context_map[e.fd]));
} else {
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_DISABLE);
}
break;
case EVFILT_TIMER:
foreach client_sock,context <- context_map {
push_queued_output(&context, computed_data(context));
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_ENABLE);
}
break;
}
}
}
I have glossed over partial send()s and recv()s, write-side shutdown, and all error handling but this is the general idea.
Further reading
https://github.com/mheily/libkqueue
Jonathan Lemon. kqueue. OpenBSD System Calls Manual.
Jonathan Lemon. kqueue. Darwin BSD Calls Manual. Apple corporation.
This is a solution using Linux epoll and timerfd (error handling is omitted):
int start_timer(unsigned int interval) {
int tfd;
struct itimerspec tspec;
tspec.it_value.tv_sec = 1;
tspec.it_value.tv_nsec = 0;
tspec.it_interval.tv_sec = 3;
tspec.it_interval.tv_nsec = 0;
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tspec, NULL);
return tfd;
}
void epset_add(int epfd, int fd, uint32_t events)
{
struct epoll_event ev;
ev.data.fd = fd;
ev.events = events;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
}
int main()
{
int epfd, tfd, sock, nfds, i;
struct epoll_event events[MAX_EVENTS];
/* create new epoll instance */
epfd = epoll_create1(0);
tfd = start_timer(TIMER_INTERVAL);
/* socket(), bind() and listen() omitted in create_socket() */
sock = create_socket(PORT_NUMBER);
/* add sock and tfd to epoll set */
epset_add(epfd, tfd, EPOLLIN);
epset_add(epfd, sock, EPOLLIN | EPOLLET);
for (;;) {
for (i = 0; i < nfds; ++i) {
if (events[i].data.fd == tfd) {
/* handle timer notification, it's run
periodically with interval TIMER_INTERVAL */
} else if (events[i].data.fd == sock) {
/* accept() incoming connections,
set non-blocking,
and add new connection sockets to epoll set */
} else {
/* recv() from connection sockets and handle */
}
}
}
}
This program was helpful https://github.com/eklitzke/epollet/blob/master/poll.c and I added timerfd to the epoll set so the server keeps listening and receiving data and at the same time can send data to the clients periodically.
I did asp.net program using mvc 4. I deployed in iis server as localhost; I want track HTTP Packet so I used SharpPcap.
Here is full code...
namespace CaseStudy
{
class Program
{
static void Main(string[] args)
{
var parmenter = SharpPcap.CaptureDeviceList.Instance;
/*If no device exists, print error */
if (parmenter.Count < 1)
{
Console.WriteLine("No device found on this machine");
return;
}
int i = 0;
Console.WriteLine("Choose Your Devices :");
Console.WriteLine("----------------------");
foreach (PcapDevice dev in parmenter)
{
/* Device Description */
Console.WriteLine("{0}] {1} [MAC:{2}]", i, dev.Interface.FriendlyName, dev.Interface.MacAddress);
i++;
}
Console.WriteLine("----------------------");
//Extract a device from the list
int deviceIndex = -1;
do
{
Console.WriteLine("Enter Your Choice :");
deviceIndex = int.Parse(Console.ReadLine());
} while (!(deviceIndex < parmenter.Count && deviceIndex >= -1));
ICaptureDevice device = parmenter[deviceIndex];
//Register our handler function to the 'packet arrival' event
//device.PcapOnPacketArrival += new SharpPcap.PacketArrivalEventHandler();
device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival);
//Open the device for capturing
//true -- means promiscuous mode
//1000 -- means a read wait of 1000ms
device.Open(DeviceMode.Promiscuous, 1000);
device.Filter = "ip and tcp";
Console.WriteLine("-- Listenning on {0}, hit 'Enter' to stop...", device.MacAddress);
//Start the capturing process
device.StartCapture();
//Wait for 'Enter' from the user.
Console.ReadLine();
//Stop the capturing process
device.StopCapture();
//Close the capturing device
device.Close();
}
private static void device_OnPacketArrival(object sender, CaptureEventArgs e)
{
DateTime time = e.Packet.Timeval.Date;
int len = e.Packet.Data.Length;
byte[] data = e.Packet.Data;
//var packet = TcpPacket.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
//Console.WriteLine(e.Packet.LinkLayerType.ToString());
Packet pack = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
if (pack is PacketDotNet.EthernetPacket)
{
var eth = pack.Extract(typeof(EthernetPacket)) as EthernetPacket;
if (len > 100)
{
Console.WriteLine("ETHERNET/INTERNET/HTTP PACKET");
//Console.WriteLine(HttpServerUtility.UrlTokenEncode(eth.Bytes));
Console.WriteLine("{0}-{1}" , eth.DestinationHwAddress, eth.SourceHwAddress);
//Console.WriteLine(eth.PayloadPacket.PayloadPacket.PrintHex());
Console.WriteLine(System.Text.Encoding.UTF8.GetString(eth.Bytes));
}
}
if (pack is PacketDotNet.TcpPacket) {
var tcp = pack.Extract (typeof(TcpPacket)) as TcpPacket;
if (len > 100)
{
//Console.WriteLine("[{0}:{1}:{2}:{3}][{4}][{5}]",
//time.Hour, time.Minute, time.Second, time.Millisecond,
//len, Stringfy.RawPacketToHex(data));
Console.WriteLine("TCP PACKET");
Console.WriteLine(tcp.PrintHex());
//Console.WriteLine(arp.SenderHardwareAddress);
}
}
if (pack is PacketDotNet.InternetPacket)
{
var inet = pack.Extract(typeof(InternetPacket)) as InternetPacket;
if (len > 100)
{
//Console.WriteLine("[{0}:{1}:{2}:{3}][{4}][{5}]",
//time.Hour, time.Minute, time.Second, time.Millisecond,
//len, Stringfy.RawPacketToHex(data));
Console.WriteLine("INTERNET PACKET");
Console.WriteLine(inet.PrintHex());
//Console.WriteLine(arp.SenderHardwareAddress);
}
}
if (pack is PacketDotNet.IpPacket)
{
var ip = pack.Extract(typeof(IpPacket)) as IpPacket;
if (len > 100)
{
//Console.WriteLine("[{0}:{1}:{2}:{3}][{4}][{5}]",
//time.Hour, time.Minute, time.Second, time.Millisecond,
//len, Stringfy.RawPacketToHex(data));
Console.WriteLine("IP PACKET");
Console.WriteLine(ip.PrintHex());
//Console.WriteLine(arp.SenderHardwareAddress);
}
}
}
}
}
this code caputuring remote server http packet like google, stackoverflow, facebook communicate with my system.
However i want track packet with my system only as a localhost.
using
any one can help? please...
It's impossible.
Why?
SharpPcap uses WinPcap and WinPcap extends the system driver to capture packets. According to WinPcap faq Question 13, it's not possible to capture the loopbackdevice aka localhost. It's a limitation of Windows not WinPcap.
I've been trying to modify the tcp server example with LwIP in STM32F4DISCOVERY board. I have to write a sender which does not necessarily have to reply server responses. It can send data with 100 ms frequency, for example.
Firstly, the example of TCP server is like this:
static void tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL) {
/* Bind connection to well known port number 7. */
err = netconn_bind(conn, NULL, DEST_PORT);
if (err == ERR_OK) {
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/* Process the new connection. */
if (newconn) {
struct netbuf *buf;
void *data;
u16_t len;
while ((buf = netconn_recv(newconn)) != NULL) {
do {
netbuf_data(buf, &data, &len);
//Incoming package
.....
//Check for data
if (DATA IS CORRECT)
{
//Reply
data = "OK";
len = 2;
netconn_write(newconn, data, len, NETCONN_COPY);
}
} while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
}
}
} else {
printf(" can not bind TCP netconn");
}
} else {
printf("can not create TCP netconn");
}
}
I modified this code to obtain a client version, this is what I've got so far:
static void tcpecho_thread(void *arg)
{
struct netconn *xNetConn = NULL;
struct ip_addr local_ip;
struct ip_addr remote_ip;
int rc1, rc2;
struct netbuf *Gonderilen_Buf = NULL;
struct netbuf *gonderilen_buf = NULL;
void *b_data;
u16_t b_len;
IP4_ADDR( &local_ip, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3 );
IP4_ADDR( &remote_ip, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
xNetConn = netconn_new ( NETCONN_TCP );
rc1 = netconn_bind ( xNetConn, &local_ip, DEST_PORT );
rc2 = netconn_connect ( xNetConn, &remote_ip, DEST_PORT );
b_data = "+24C"; // Data to be send
b_len = sizeof ( b_data );
while(1)
{
if ( rc1 == ERR_OK )
{
// If button pressed, send data "+24C" to server
if (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET)
{
Buf = netbuf_new();
netbuf_alloc(Buf, 4); // 4 bytes of buffer
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
vTaskDelay(100); // To see the result easily in Comm Operator
netbuf_delete(Buf);
}
}
if ( rc1 != ERR_OK || rc2 != ERR_OK )
{
netconn_delete ( xNetConn );
}
}
}
While the writing operation works, netconn_write sends what's on its buffer. It doesnt care whether b_data is NULL or not. I've tested it by adding the line b_data = NULL;
So the resulting output in Comm Operator is like this:
Rec:(02:47:27)+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C
However, I want it to work like this:
Rec:(02:47:22)+24C
Rec:(02:47:27)+24C
Rec:(02:57:12)+24C
Rec:(02:58:41)+24C
The desired write operation happens when I wait for around 8 seconds before I push the button again.
Since netconn_write function does not allow writing to a buffer, I'm not able to clear it. And netconn_send is only allowed for UDP connections.
I need some guidance to understand the problem and to generate a solution for it.
Any help will be greately appreciated.
It's just a matter of printing the result in the correct way.
You can try to add this part of code before writing in the netbuf data structure:
char buffer[20];
sprintf(buffer,"24+ \n");
Buf->p->payload = "+24C";
I see one or two problems in your code, depending on what you want it exactly to do. First of all, you're not sending b_data at all, but a constant string:
b_data = "+24C"; // Data to be send
and then
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
b_data is not anywhere mentioned there. What is sent is the payload. Try Buf->p->payload = b_data; if it's what you want to achieve.
Second, if you want the +24C text to be sent only once when you push the button, you'll have to have a loop to wait for the button to open again before continuing the loop, or it will send +24C continuously until you stop pushing the button. Something in this direction:
while (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET) {
vTaskDelay(1);
}
When I execute the following:
private function setUpRecvStream():void {
writeText("Connecting to: " + theirID);
recvStream = new NetStream(netConnection, theirID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
//play the recvStream
recvStream.play("media");
//attach the stream videoRecv
videoRecv.attachNetStream(recvStream);
}
Using a vaild string for theirID I'm getting the following:
Connecting to: 8640d30e760528b2c88662eacef67d693527e52549eb5e29fc405355a7db147e
NetStream.Connect.Closed
I'm expecting NetStream.Connect.Success since I'm passing in a vaild string for theirID. Any ideas why this might be happening?
Are you initializing your netConnection? Also, the stream you are connecting to might not be publishing "media".
The client you are connecting to must do sendStream.publish("media")
before using this you need to connect to FMS
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusEvent);
nc.connect('rtmfp://stratus.adobe.com/cbd2224f9a56771b3d4d05c3-bd9b549abca2');
private function netStatusEvent(event:NetStatusEvent):void {
trace('NetConnection status event (1): ' + event.info.code);
if (event.info.code == 'NetConnection.Connect.Success'){
}
}