Don't get confused by me talking about L2TP. Although my problem is related to L2TP it is not an L2TP problem per se. It's more of an networking problem.
Background
I'm writing an application working with L2TP. This is my first time working with L2TP and the linux L2TP subysytem, so I hope I got all this right.
When creating an L2TP Ethernet session the subsystem automatically creates a virtual network interface.
After bringing the interface up I can check with Wireshark and indeed the desired data is sent to the interface. This is without any packaging tho. It's not inside an ethernet frame or anything, but just the data bytes which were included in the L2TP packet.
I have no control over actually creating the device, but I can query its name and therefore its index etc., so so far so good.
The actual problem
My question is actually pretty simple: How do I get the data which is sent to a virtual interface into my userspace application?
I don't have a lot of experience with networking on unix but my expectation would be that this is a fairly simple problem, solvable by either obtaining an file descriptor with which I can use read / recv or somehow binding a socket to just that network interface.
I couldn't find any (gen-)netlink / ioctl API (or anything else) to do this or something comparable.
Although my application is written in GO not in C, a solution in C would be completely sufficient. Tbh at this point I would be happy about any approach to solve this issue programmatically. :)
Thanks a lot in advance
I just found a tutorial which answers my own question. It was actually really easy using AF_PACKET sockets.
There is a lovely tutorial on microhowto.info, which explains how AF_PACKET sockets work, better than I ever could. It even includes a section "Capture only from a particular network interface".
Here is a minimal example, which worked for my use case:
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <linux/if_packet.h>
#include <sys/socket.h>
// [...]
// Create socket
int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (fd == -1) {
perror("ERROR socket");
exit(1);
}
// Interface index (i.e. obtainable via ioctl SIOCGIFINDEX)
int ifindex = 1337;
// create link layer socket address
struct sockaddr_ll addr = {0};
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifindex;
addr.sll_protocol = htons(ETH_P_ALL)
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("ERROR bind");
exit(1);
}
char buffer[65535];
ssize_t len;
do {
len = recv(fd, buffer, sizeof(buffer) -1, 0);
if (len < 0) {
perror("ERROR recvfrom");
exit(1);
}
printf("recived data (length: %i)\n", (int) len);
} while (len > 0);
Related
I'm writing a simple program that creates an ethernet I frame and sends it through an interface to the specified MAC.
As i have read, the process for connecting to a socket in UNIX goes a bit like:
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
/* populate sll with the target and interface info */
connect(sockfd, (struct sockaddr*)&sll, sizeof(sll));
write(sockfd, stuff, sizeof(stuff));
close(sockfd)
The thing is, for me, stuff is a valid eth frame already containing everything needed to send a packet to its destination. Isn't the connect step redundant then? What am I missing?
Have a nice day.
Not only is the connect "redundant", it is an error -- according to the Linux man page:
The connect(2) operation is not supported on packet sockets.
So the connect is probably failing but not actually doing anything. Since you ignore the return value of connect, you don't notice the failure.
As stated above, the connection step was wrong.
I will give the details of how i solved it in this post in case anyone in need sees this: (this is as i understood it, feel free to correct me)
For a trully raw communication in userspace you have to understand three concepts:
Sockets are analogous to file descriptors.
Binding a socket is like opening a file.
You can not read or write to a socket, just kindly ask the kernel to do it for you.
The process i followed is as follows:
int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET;
sll.sll_ifindex = index; //This is the index of your network card
//Can be obtained through ioctl with SIOCGIFINDEX
sll.sll_protocol = htons(ETH_P_ALL);
bind(sockfd, (struct sockaddr*)&sll, sizeof(sll));
size_t send_len = write(sockfd, data, size);
As you can see, we dont really use connect, as it was, indeed, a mistake.
p.s. for a full example: https://github.com/TretornESP/RAWRP
Before I get started. Yes, I could use leJOS, ev3dev, or some others, but I'd like to do it this way because that is how I learn.
I am using the CodeSourcery arm-2009q1 arm toolchain. I fetched the required libraries (bluetooth) from here: https://github.com/mindboards/ev3sources.
I am uploading the programs to the brick by using this tool: https://github.com/c4ev3/ev3duder
I have also fetched the brick's shared libraries, but I can not get them to work properly and there is 0 documentation on how to write a c program for the ev3 using the shared libraries. If I could get that working I might be able to use the c_com module to handle bluetooth, but right now bluez and rfcomm in conjunction with: https://github.com/c4ev3/EV3-API for motor and sensor control seems to be my best bet.
Now, with that out of the way:
I'd like to run the EV3 as a bluetooth "server" meaning that I start a program on it and the program opens a socket, binds it, listens for a connection, and then accepts a single connection.
I am able to do open a socket, bind it to anything but channel 1 (I believe this might be the crux of my issue), I am able to listen. These all return 0 (OK) and everything is fine.
Then I try to accept a connection. That instantly returns -1 and sets the remote to address 00:00:00:00:00:00.
My code is pretty much the same as can be found here: https://people.csail.mit.edu/albert/bluez-intro/x502.html
Here it is:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <ev3.h>
int main(int argc, char **argv)
{
InitEV3();
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int sock, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = 2; // <-- Anything but 1. 1 seems to be taken
bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
listen(sock, 1);
// accept one connection <-- PROGRAM FAILS HERE AS accept() returns -1
client = accept(sock, (struct sockaddr *)&rem_addr, &opt);
// ---- All following code is irrelevant because accept fails ----
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 )
printf("received [%s]\n", buf);
close(client);
close(sock);
FreeEV3();
return 0;
}
I am able to get the same code working on my pi. Even communication back and forth when the ev3api-specific functions are commented out. I just can't fathom why it won't work on the EV3.
I figured it out.
On my raspberry PI, the accept call worked as expected with no quirks. On the EV3 however, the accept call is non-blocking even if it has not been told to act like so.
The solution was to place the accept call in a loop until an incoming connection was in the queue.
while (errno == EAGAIN && ButtonIsUp(BTNEXIT) && client < 0)
client = accept(sock, (struct sockaddr*)&rem_addr, sizeof(rem_addr));
I'll upload the code to github. Contact me if you'd like to do something similar with the EV3.
I'm trying to port my desktop app written in C and C++ to webassembly platform and am investigating if it is possible at all. One of important things the app does is communicate by sending and receiving UDP messages. I have implemented minimal UDP client which just creates UDP socket and sends packets to server (which is build natively and is running as separate executable at the same machine). socket, bind and sendto APIs return no error and everything looks working but no messages are receiving on server side and wireshark shows no activity on that port.
Is UDP socket just stubbed at webassembly libc port, or it is implemented on top of some web standard connection (e.g. WebRTC)?
The client code is below. I checked that native build is working properly.
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFLEN 512
#define NPACK 100
#define PORT 9930
void diep(char *s)
{
perror(s);
exit(1);
}
#define SRV_IP "127.0.0.1"
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
for (i=0; i<NPACK; i++) {
printf("Sending packet %d\n", i);
sprintf(buf, "This is packet %d\n", i);
if (sendto(s, buf, BUFLEN, 0, (struct sockaddr*)&si_other, slen)==-1)
diep("sendto()");
}
close(s);
return 0;
}
I followed instructions from http://webassembly.org/getting-started/developers-guide/ to build and run it.
Thanks in advance for any help or clues!
I found how UDP sockets are implemented at webassembly. Actually, they are emulated by websockets. It probably would work if both client and server were webassemblies, but my server is built natively. As wasm doesn't support dynamic linking, all the code (including libc implementation) is bundled to one JS file, were we can find UDP sendto implementation:
// if we're emulating a connection-less dgram socket and don't have
// a cached connection, queue the buffer to send upon connect and
// lie, saying the data was sent now.
if (sock.type === 2) {
if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
// if we're not connected, open a new connection
if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
}
dest.dgram_send_queue.push(data);
return length;
}
}
Anything that runs in the browser will not give you native socket access and I suspect that browser vendors would strongly object to any such access as it is a potential security violation.
Perhaps as more and more native applications move to the web as the performance difference shrinks due to webassembly and similar initiatives would make them change their stance, but until then, anything that wants direct socket control would have to remain a native app.
I wish to send UDP multicast packets to loopback address and receive the same in other application. All tests done on fedora core 17 Linux.
The idea is to receive a video stream via RTSP/HTTP or any other network protocol and multicast it on the loopback address so that I can use VLC to play the stream using multicast address. Leaving aside other bitrate and controlled multicast issues, I tried to read one video file and multicast on loopback device. But when tried to play the same on vlc it didn't worked. I'm able to see packet getting transmitted in wireshark but the src ip is taken from my default network interface (i.e interface which is my default gateway)
I have already tried following commands
sudo ifconfig lo multicast
sudo ip route add 239.252.10.10 dev lo
Any suggestion in this regard would be very helpful.
Test program code pasted below
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MULTICAST_ADDRESS "239.252.10.10"
#define UDP_PORT 1234
#define INTERFACE_IP "127.0.0.1"
#define MTU 1474
#define DATA_BUFFER_SIZE (1024*1024)
static int socket_init(char *intf_ip) {
int sd;
struct in_addr localInterface;
sd = socket (AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
perror ("Opening datagram socket error");
return -1;
}
else
printf ("Opening the datagram socket...OK.\n");
localInterface.s_addr = inet_addr (intf_ip);
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &localInterface,sizeof (localInterface)) < 0){
perror ("Setting local interface error");
close(sd);
return -1;
}
else
printf ("Setting the local interface...OK\n");
#if 1
char loopch = 1;
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0){
perror("Setting IP_MULTICAST_LOOP error");
close(sd);
return -1;
}
else
printf("Enabling the loopback...OK.\n");
#endif
return sd;
}
static int transmit_packet(int sd, char *databuf, int size,char *ip, unsigned short port){
struct sockaddr_in groupSock;
int len,datalen,rc;
memset ((char *) &groupSock, 0, sizeof (groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr (ip);
groupSock.sin_port = htons (port);
len=0;
datalen = MTU;
if(size < MTU)
datalen = size;
while(len < size){
rc = sendto(sd, databuf, datalen, 0, (struct sockaddr *) &groupSock,sizeof (groupSock));
if(rc <0){
perror ("Sending datagram message error");
return -1;
}
usleep(10000);
len += rc;
}
return len;
}
static int transmit_file(char *filepath, char *dstip, char *srcip,unsigned short port) {
FILE *fp;
int sd,rc;
char *databuf;
fp = fopen(filepath, "r");
if(!fp) {
printf("transmit_file : no such file or directory %s \n",filepath);
return -1;
}
sd = socket_init(srcip);
if(sd < 0) {
printf("Socket initialization failed \n");
fclose(fp);
return -1;
}
databuf = (char*) malloc(sizeof(char)*DATA_BUFFER_SIZE);
if(!databuf) {
printf("Unable to allocate databuf\n");
close(sd);fclose(fp);
return -1;
}
while(!feof(fp)){
rc = fread(databuf,1,DATA_BUFFER_SIZE,fp);
if(rc<= 0) {
printf("read failed or EOF reached\n");
break;
}
if(transmit_packet(sd,databuf,rc,dstip,port) <0)
printf("Transmit failed\n");
}
close(sd);fclose(fp);
free(databuf);
return 0;
}
int main(int argc, char *argv[]){
if(argc != 3){
printf("%s <filename> <ip>\n",argv[0]);
return -1;
}
transmit_file(argv[1],argv[2],INTERFACE_IP,UDP_PORT);
return 0;
}
You can use multicast on loopback but you have to add a new route because your OS using default external interface by default for multicast. Also multicast can be disabled by default on loopback. On linux you can change this with this command :
route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
ifconfig lo multicast
Binding or routing to the loopback device is necessary if you do not want IP multicast traffic (such as IGMP messages) to be sent across the network. However, this is typically only necessary if there are other computers on the network that may interfere by using the same multicast group.
The real problem is having programs on the same host receive multicast data sent by each other (or, equivalently, having sockets within a single program receive multicast data sent by each other), when they're both configured to use the same multicast group.
This is quite a common question with many StackOverflow questions on it, but they are often misunderstood or poorly worded. It is difficult to search for this problem specifically with regards to operating system behavior or standardization.
On the hardware level, multicast traffic is treated like broadcast traffic in that it is not routed back to the physical port it was sent from in order to prevent link level loops. This means that the operating system is responsible for forwarding traffic to other programs or sockets on the same host that joined a multicast group, since it won't be read from the interface.
This is configured by the standard IP_MULTICAST_LOOP option, which is best summarized by the IP Multicast MSDN article (archived):
Currently, most IP multicast implementations use a set of socket options proposed by Steve Deering to the Internet Engineering Task Force (IETF). Five operations are thus made available:
[...]
IP_MULTICAST_LOOP—Controls loopback of multicast traffic.
[...]
The Winsock version of the IP_MULTICAST_LOOP option is semantically different than the UNIX version of the IP_MULTICAST_LOOP option:
In Winsock, the IP_MULTICAST_LOOP option applies only to the receive path.
In the UNIX version, the IP_MULTICAST_LOOP option applies to the send path.
For example, applications ON and OFF (which are easier to [keep track of] than X and Y) join the same group on the same interface; application ON sets the IP_MULTICAST_LOOP option on, application OFF sets the IP_MULTICAST_LOOP option off. If ON and OFF are Winsock applications, OFF can send to ON, but ON cannot sent to OFF. In contrast, if ON and OFF are UNIX applications, ON can send to OFF, but OFF cannot send to ON.
From what I have read this is setting may be disabled by default on Windows and enabled by default on Linux, but I haven't tested it myself.
As an important side note, the IP_MULTICAST_LOOP option is entirely different from the IPV6_MULTICAST_LOOP option, referring to the Linux ip(7) and ipv6(7) man pages:
IP_MULTICAST_LOOP (since Linux 1.2)
Set or read a boolean integer argument that determines whether sent multicast packets should be looped back to the local sockets.
IPV6_MULTICAST_LOOP
Control whether the socket sees multicast packets that it has [sent] itself. Argument is a pointer to boolean.
IP_MULTICAST_LOOP allows IP multicast traffic to be received on different sockets on the same host it was sent. IPV6_MULTICAST_LOOP allows IPv6 multicast traffic to be received on the same socket it was sent -- something which is not typically possible with IPv4.
If anyone has references to official standards about the intended behavior of implementations (RFCs, IEEE POSIX standards, etc.), please post them in the comments or edit this answer.
I wish to send UDP multicast packets to loopback address
Stop right there. You can't do that. It's impossible. You can only send multicasts to multicast addresses. Your code doesn't do any multicasting, just sending to 127.0.0.1.
If you're only sending to the localhost, why are you using multicast at all? Do you have multiple listening processes?
the src ip is taken from my default network interface(i.e interface which is my default gateway)
Very likely, as you haven't bound your socket. What did you expect?
I have written an HTTP proxy that does some stuff that's not relevant here, but it is increasing the client's time-to-serve by a huge amount (600us without proxy vs 60000us with it). I think I have found where the bulk of that time is coming from - between my proxy finishing sending back to the client and the client finishing receiving it. For now, server, proxy and client are running on the same host, using localhost as the addresses.
Once the proxy has finished sending (once it has returned from send() at least), I print the result of gettimeofday which gives an absolute time. When my client has received, it prints the result of gettimeofday. Since they're both on the same host, this should be accurate. All send() calls are with no flags, so they are blocking. The difference between the two is about 40000us.
The proxy's socket on which it listens for client connections is set up with the hints AF_UNSPEC, SOCK_STREAM and AI_PASSIVE. Presumably a socket from accept()ing on that will have the same parameters?
If I'm understanding all this correctly, Apache manages to do everything in 600us (including the equivalent of whatever is causing this 40000us delay). Can anybody suggest what might be causing this? I have tried setting the TCP_NODELAY option (I know I shouldn't, it's just to see if it made a difference) and the delay between finishing sending and finishing receiving went right down, I forget the number but <1000us.
This is all on Ubuntu Linux 2.6.31-19. Thanks for any help
40ms is the TCP ACK delay on Linux, which indicates that you are likely encountering a bad interaction between delayed acks and the Nagle algorithm. The best way to address this is to send all of your data using a single call to send() or sendmsg(), before waiting for a response. If that is not possible then certain TCP socket options including TCP_QUICKACK (on the receiving side), TCP_CORK (sending side), and TCP_NODELAY (sending side) can help, but can also hurt if used improperly. TCP_NODELAY simply disables the Nagle algorithm and is a one-time setting on the socket, whereas the other two must be set at the appropriate times during the life of the connection and can therefore be trickier to use.
You can't really do meaningful performance measurements on a proxy with the client, proxy and origin server on the same host.
Place them all on different hosts on a network. Use real hardware machines for them all, or specialised hardware test systems (e.g. Spirent).
Your methodology makes no sense. Nobody has 600us of latency to their origin server in practice anyway. Running all the tasks on the same host creates contention and a wholly unreaslistic network environment.
INTRODUCTION:
I already praised mark4o for the truly correct answer to the general question of lowering latency. I would like to translate the answer in terms of how it helped solve my latency issue because I think it's going to be the answer most people come here looking for.
ANSWER:
In a real-time network app (such as a multiplayer game) where getting short messages between nodes as quickly as possible is critical, TURN NAGLE OFF. In most cases this means setting the "no-delay" flag to true.
DISCLAIMER:
While this may not solve the OP specific problem, most people who come here will probably be looking for this answer to the general question of their latency issues.
ANECDOTAL BACK-STORY:
My game was doing fine until I added code to send two messages separately, but they were very close to each other in execution time. Suddenly, I was getting 250ms extra latency. As this was a part of a larger code change, I spent two days trying to figure out what my problem was. When I combined the two messages into one, the problem went away. Logic led me to mark4o's post and so I set the .Net socket member "NoDelay" to true, and I can send as many messages in a row as I want.
From e.g. the RedHat documentation:
Applications that require lower latency on every packet sent should be run on sockets with TCP_NODELAY enabled. It can be enabled through the setsockopt command with the sockets API:
int one = 1;
setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
For this to be used effectively, applications must avoid doing small, logically related buffer writes. Because TCP_NODELAY is enabled, these small writes will make TCP send these multiple buffers as individual packets, which can result in poor overall performance.
In your case, that 40ms is probably just a scheduler time quantum. In other words, that's how long it takes your system to get back round to the other tasks. Try it on a real network, you'll get a completely different picture. If you have a multi-core machine, using virtual OS instances in Virtualbox or some other VM would give you a much better idea of what is really going to happen.
For a TCP proxy it would seem prudent on the LAN side to increase the TCP initial window size as discussed on linux-netdev and /. recently.
http://www.amailbox.org/mailarchive/linux-netdev/2010/5/26/6278007
http://developers.slashdot.org/story/10/11/26/1729218/Google-Microsoft-Cheat-On-Slow-Start-mdash-Should-You
Including paper on the topic by Google,
http://www.google.com/research/pubs/pub36640.html
And an IETF draft also by Google,
http://zinfandel.levkowetz.com/html/draft-ietf-tcpm-initcwnd-00
For Windows, I'm not sure if setting TCP_NODELAY helps. I tried that, but latency was still bad. One person suggested I try UDP, and that did the trick.
A few complicated examples of UDP did not work for me, but I ran across a simple one and it did the trick...
#include <Winsock2.h>
#include <WS2tcpip.h>
#include <system_error>
#include <string>
#include <iostream>
class WSASession
{
public:
WSASession()
{
int ret = WSAStartup(MAKEWORD(2, 2), &data);
if (ret != 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "WSAStartup Failed");
}
~WSASession()
{
WSACleanup();
}
private:
WSAData data;
};
class UDPSocket
{
public:
UDPSocket()
{
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
throw std::system_error(WSAGetLastError(), std::system_category(), "Error opening socket");
}
~UDPSocket()
{
closesocket(sock);
}
void SendTo(const std::string& address, unsigned short port, const char* buffer, int len, int flags = 0)
{
sockaddr_in add;
add.sin_family = AF_INET;
add.sin_addr.s_addr = inet_addr(address.c_str());
add.sin_port = htons(port);
int ret = sendto(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&add), sizeof(add));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "sendto failed");
}
void SendTo(sockaddr_in& address, const char* buffer, int len, int flags = 0)
{
int ret = sendto(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&address), sizeof(address));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "sendto failed");
}
sockaddr_in RecvFrom(char* buffer, int len, int flags = 0)
{
sockaddr_in from;
int size = sizeof(from);
int ret = recvfrom(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&from), &size);
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "recvfrom failed");
// make the buffer zero terminated
buffer[ret] = 0;
return from;
}
void Bind(unsigned short port)
{
sockaddr_in add;
add.sin_family = AF_INET;
add.sin_addr.s_addr = htonl(INADDR_ANY);
add.sin_port = htons(port);
int ret = bind(sock, reinterpret_cast<SOCKADDR *>(&add), sizeof(add));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "Bind failed");
}
private:
SOCKET sock;
};
Server
#define TRANSACTION_SIZE 8
static void startService(int portNumber)
{
try
{
WSASession Session;
UDPSocket Socket;
char tmpBuffer[TRANSACTION_SIZE];
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData=0;
input.mi.dwFlags = MOUSEEVENTF_MOVE;
Socket.Bind(portNumber);
while (1)
{
sockaddr_in add = Socket.RecvFrom(tmpBuffer, sizeof(tmpBuffer));
...do something with tmpBuffer...
Socket.SendTo(add, data, len);
}
}
catch (std::system_error& e)
{
std::cout << e.what();
}
Client
char *targetIP = "192.168.1.xxx";
Socket.SendTo(targetIP, targetPort, data, len);