UDP Server not receiving in Unix (Cygwin) - unix

So I've looked around and noticed some others having a similar problem to mine. However I have yet to find a solution. I've created a client and server in Unix (Cygwin) using UDP. When I try to use sendto() in order to send a message to the server from the client, the server doesn't seem to be receiving the the packet. I've done error checking and it seems like the client isn't having a problem sending the packet, yet still the server cannot receive it correctly. The server just seems to be dead for the most part. I'm using my machine to host the client and the server and I'm attempting to connect to the server on my home address (127.0.0.1) and a random port. Any suggestions at this point would be much appreciated.
Server Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() / atof() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h> /* String manipulation */
#include <time.h> /* Used to to measure process execution time */
/* Server main routine - this is an iterative server
1. create a socket
2. bind the socket and print out the port number assigned
3. do forever
get next connection
handle the connection
enddo
*/
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
int n;
//Create UDP socket
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Problem creating socket\n");
exit(1);
}
//Setup the UDP server
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(0);
//Bind the UDP to the socket
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0)
{
perror("Error bind\n");
exit(1);
}
//Print the port for the UDP server
int length = sizeof( servaddr );
if (getsockname(sockfd, (struct sockaddr *) &servaddr, &length) < 0)
{
perror("Error getsockname\n");
exit(1);
}
printf("The Server passive socket port number is %d\n",ntohs(servaddr.sin_port));
//Send/Recv from client
char msg[100];
for(;;)
{
socklen_t len = sizeof(cliaddr);
if( recvfrom(sockfd, msg, 100, 0, (struct sockaddr*) &cliaddr, &len) < 0)
{
perror("Error on recv\n");
exit(1);
}
printf("Msg: %s\n", msg);
//read(sockfd, msg, 10);
//sendto(sockfd, msg, n, 0, (struct sockaddr*) &cliaddr, len);
}
close(sockfd);
return 0;
}
Client Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h>
/* client program:
The following must passed in on the command line:
name of the server (argv[1])
port number of the server (argv[2])
*/
int main( int argc, char **argv )
{
int sockfd;
struct sockaddr_in servaddr;
int n;
//Ensure we have full args
if (argc != 3)
{
printf("Usage: client <server name> <server port>\n");
exit(1);
}
//Setup the port number
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
//Setup the client IP
//inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) <= 0
if( inet_aton(argv[1], &servaddr.sin_addr) == 0)
{
perror("Error with server IP\n");
exit(1);
}
//Create socket
if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error on socket\n");
exit(1);
}
/*if (connect(sockfd,(struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Problem connecting socket\n");
exit(1);
}*/
//Send msg
char msg[10] = "123456789";
for(;;)
{
socklen_t len = sizeof(servaddr);
if( (sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*) &servaddr, len)) < 0 )
{
perror("Error on sendto():\n");
exit(1);
}
//write(sockfd, msg, strlen(msg));
//n = recvfrom(sockfd, msg2, 10, 0, NULL, NULL);
//printf("Msg: %s\n", msg2);
}
close(sockfd);
return 0;
}

First, your sender just sends data as fast as it possibly can, whether or not anyone or anything is listening. That's not a good thing to do.
Second, your receiver passes msg through to a %s printf specifier. But %s is only for C-style strings, and msg is not a C-style string (nothing puts a zero byte on the end of it). You also throw the return value of recvfrom away, so you can't convert it into a string because you have no idea how many of its bytes are valid.
Third, your server is creating a SOCK_STREAM socket!

Related

Socket programming in R to receive UDP stream

In Python I am able to write a code for socket programming to receive a Data stream via UDP.
However, how can I have an equivalent code in R to do the same?
import socket, traceback
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))
counter = 1500
while counter > 0:
counter -= 1
try:
message, address = s.recvfrom(8192)
message = message.decode()
data = message.split(",")
print(data)
except (KeyboardInterrupt, SystemExit):
raise
except:
traceback.print_exc()
In R I tried with below code, which is not successful. I do realize I need to somewhere mention that its is UDP and all, but unable to find those settings.
I need to receive the 'Stream' of Data from a Device.
Do I need to have R-server for this?
platform x86_64-pc-linux-gnu
os linux-gnu
version.string R version 3.2.3 (2015-12-10)
RStudio Version 1.0.44
server <- function(){
while(TRUE){
writeLines("Listening...")
con <- socketConnection(host="localhost", port = 5555, blocking=TRUE,server=TRUE, open="r+")
data <- readLines(con, 1)
print(data)
close(con)
}
}
server()
JF,
My sense would be to write your code directly in C / C++ and include in your R program via the
R Rcpp package.
Using the above approach you can create a package that mimics the python functionality or just wrap the python code inside an RCPP package directly. This last point is covered in the following tutorial
Call Python from R through RCPP
I hope the above explanation and code example below will help point you in the right direction.
Rcpp code example:
Listener.R
setwd("~/dev/stackoverflow/40896072")
# install.packages("installr")
# require(installr)
# install.Rtools()
# install.packages("Rcpp")
# # Test and Verify
# Rcpp::evalCpp("2+2")
Rcpp::sourceCpp( file = "./listener.cc")
listen()
Listener.cc
/* listener.c - a datagram socket 'server'
* simply displays message received then dies!
*/
#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 <Rcpp.h>
using namespace Rcpp;
#define MYPORT 5555 /* the port users connect to */
#define MAXBUFLEN 100
// [[Rcpp::export]]
int listen() {
int sockfd;
struct sockaddr_in my_addr; /* info for my addr i.e. server */
struct sockaddr_in their_addr; /* client's address info */
socklen_t addr_len;
ssize_t numbytes;
char buf[ MAXBUFLEN];
printf( "Running\n");
if( (sockfd = socket( AF_INET, SOCK_DGRAM, 0)) == -1) {
perror( "Listener socket");
exit( 1);
}
memset( &my_addr, 0, sizeof( my_addr)); /* zero struct */
my_addr.sin_family = AF_INET; /* host byte order ... */
my_addr.sin_port = htons( MYPORT); /* ... short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* any of server IP addrs */
if( bind( sockfd, (struct sockaddr *)&my_addr,
sizeof( struct sockaddr)) == -1) {
perror( "Listener bind");
exit( 1);
}
addr_len = sizeof( struct sockaddr);
if( (numbytes = recvfrom( sockfd, buf, MAXBUFLEN - 1, 0,
(struct sockaddr *) &their_addr, &addr_len)) == -1) {
perror( "Listener recvfrom");
exit( 1);
}
printf( "Got packet from %s\n", inet_ntoa( their_addr.sin_addr));
printf( "Packet is %zd bytes long\n", numbytes);
buf[ numbytes] = '\0'; /* end of string */
printf( "Packet contains \"%s\"\n", buf);
close( sockfd);
return 0;
}
Client.R
setwd("~/dev/stackoverflow/40896072")
# install.packages("installr")
# require(installr)
# install.Rtools()
# install.packages("Rcpp")
# # Test and Verify
# Rcpp::evalCpp("2+2")
Rcpp::sourceCpp( file = "./client.cc")
client()
Client.cc
/* client.c - a datagram 'client'
*/
#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> /* for gethostbyname() */
//#include <Rcpp.h>
//using namespace Rcpp;
#define PORT 5555 /* server port the client connects to */
// [[Rcpp::export]]
int client()
{
socklen_t sockfd;
ssize_t numbytes;
struct hostent *he;
struct sockaddr_in their_addr; /* server address info */
/* resolve server host name or IP address */
if ( (he = gethostbyname("localhost")) == NULL )
{
perror( "Talker gethostbyname");
exit( 1);
}
if ( (sockfd = socket( AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror( "Talker socket");
exit( 1);
}
memset( &their_addr,0, sizeof(their_addr) ); /* zero struct */
their_addr.sin_family = AF_INET; /* host byte order .. */
their_addr.sin_port = htons( PORT); /* .. short, netwk byte order */
their_addr.sin_addr = *( (struct in_addr *)he -> h_addr);
if( (numbytes = sendto( sockfd, "Hello", strlen("Hello"), 0,
(struct sockaddr *) &their_addr,
sizeof( struct sockaddr))) == -1)
{
perror( "Talker sendto");
exit( 1);
}
printf( "Sent %zd bytes to %s\n", numbytes,
inet_ntoa( their_addr.sin_addr));
close( sockfd );
return 0;
}
Runtime output
Is RMarkdown helpful for you to write your python code in and run it?
---
title: "socket_prog"
output: html_document
---
```{python}
import socket, traceback
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))
counter = 1500
while counter > 0:
counter -= 1
try:
message, address = s.recvfrom(8192)
message = message.decode()
data = message.split(",")
print(data)
except (KeyboardInterrupt, SystemExit):
raise
except:
traceback.print_exc()
```
If R make.socket won't play nice w/UDP just use socat to either relay UDP as TCP or pipe incoming data R.

TCP optimisation

I've written a code using SOL_SOCKET protocol but getting error as 10043 (error in socket).
The code is as follows:
#include <QCoreApplication>
#include<QDebug>
//#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
/****************************************/
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
/****************************************/
#define DEFAULT_BUFLEN 512
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN];
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WSADATA wsaData;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
//hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = SOL_SOCKET;
//hints.ai_protocol = IPPROTO_TCP;
#define DEFAULT_PORT "10990"
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ConnectSocket = INVALID_SOCKET;
// Attempt to connect to the first address returned by
// the call to getaddrinfo
ptr=result;
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
int rcvbuf = 8192; /* recv buffer size */
int z = setsockopt(ConnectSocket,SOL_SOCKET,SO_RCVBUF,
(char*)&rcvbuf,sizeof(rcvbuf));
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult > 0);
return a.exec();
}
When I run it shows::
Error in socket:10043
I googled it and found that the error is because of wrong protocol for the socket type,I tried to find the correct protocol and socket type match but couldn't find.I tried every possible socket option and protocol match.
Any body facing the same problem?
You're putting the wrong value in the ai_protocol field. It needs to be one of the IPPROTO_ constants (like e.g. IPPROTO_TCP or IPPROTO_ICMP).
SOL_SOCKET is used to set socket options (like you do later in the code).
You should normally not set that member, except to zero.

Can't seem to get C TCP Server-Client Communications Right

I need some serious help here. I have to make a TCP Server Client. When the Client connects to server using a three stage handshake. Afterwards, while the Client is running in the terminal, the user enters Linux shell commands like xinput list, ls -1, etc — something that uses standard output. The server accepts the commands and uses system() (in a fork() in an infinite loop) to run the commands and the standard output is redirected to the client, where the client prints out each line.
Afterward the server sends a completion signal of "\377\n". In which the client goes back to the command prompt asking for a new command and closes its connection and exit()'s when inputting "quit".
I know that you have to dup2() both the STDOUT_FILENO and STDERR_FILENO to the client's file descriptor {dup2(client_FD, STDOUT_FILENO). Everything works except when it comes for the client to retrieve system()'s stdout and printing it out... all I get is a blank line with a blinking cursor (client waiting on stdin). I tried all kinds of different routes to no avail... If anyone can help out I would greatly appreciate it
TCP SERVER CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
//Prototype
void handle_client(int connect_fd);
int main()
{
int server_sockfd, client_sockfd;
socklen_t server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
/* Create a connection queue, ignore child exit details and wait for clients. */
listen(server_sockfd, 10);
signal(SIGCHLD, SIG_IGN);
while(1) {
printf("server waiting\n");
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
if(fork() == 0)
handle_client(client_sockfd);
else
close(client_sockfd);
}
}
void handle_client(int connect_fd) {
const char* remsh = "<remsh>\n";
const char* ready = "<ready>\n";
const char* ok = "<ok>\n";
const char* command = "<command>\n";
const char* complete = "<\377\n";
const char* shared_secret = "<shapoopi>\n";
static char server_msg[201];
static char client_msg[201];
static char commands[201];
int sys_return;
//memset client_msg, server_msg, commands
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(client_msg));
memset(&commands, 0, sizeof(commands));
//read remsh from client
read(connect_fd, &client_msg, 200);
//check remsh validity from client
if(strcmp(client_msg, remsh) != 0) {
errno++;
perror("Error Establishing Handshake");
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write remsh to client
write(connect_fd, remsh, strlen(remsh));
//read shared_secret from client
read(connect_fd, &client_msg, 200);
//check shared_secret validity from client
if(strcmp(client_msg, shared_secret) != 0) {
errno++;
perror("Invalid Security Passphrase");
write(connect_fd, "no", 2);
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write ok to client
write(connect_fd, ok, strlen(ok));
// dup2 STDOUT_FILENO <= client fd, STDERR_FILENO <= client fd
dup2(connect_fd, STDOUT_FILENO);
dup2(connect_fd, STDERR_FILENO);
//begin while... while read (client_msg) from server and >0
while(read(connect_fd, &client_msg, 200) > 0) {
//check command validity from client
if(strcmp(client_msg, command) != 0) {
errno++;
perror("Error, unable to retrieve data");
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write ready to client
write(connect_fd, ready, strlen(ready));
//read commands from client
read(connect_fd, &commands, 200);
//run commands using system( )
sys_return = system(commands);
//check success of system( )
if(sys_return < 0) {
perror("Invalid Commands");
errno++;
}
//memset commands
memset(commands, 0, sizeof(commands));
//write complete to client
write(connect_fd, complete, sizeof(complete));
}
}
TCP CLIENT CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "readline.c"
int main(int argc, char *argv[])
{
int sockfd;
int len;
struct sockaddr_in address;
int result;
const char* remsh = "<remsh>\n";
const char* ready = "<ready>\n";
const char* ok = "<ok>\n";
const char* command = "<command>\n";
const char* complete = "<\377\n";
const char* shared_secret = "<shapoopi>\n";
static char server_msg[201];
static char client_msg[201];
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(server_msg));
/* Create a socket for the client. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server. */
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(argv[1]);
address.sin_port = htons(9734);
len = sizeof(address);
/* Now connect our socket to the server's socket. */
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == -1) {
perror("ACCESS DENIED");
exit(1);
}
//write remsh to server
write(sockfd, remsh, strlen(remsh));
//read remsh from server
read(sockfd, &server_msg, 200);
//check remsh validity from server
if(strcmp(server_msg, remsh) != 0) {
errno++;
perror("Error Establishing Initial Handshake");
close(sockfd);
exit(1);
}
//memset server_msg
memset(&server_msg, 0, sizeof(server_msg));
//write shared secret text to server
write(sockfd, shared_secret, strlen(shared_secret));
//read ok from server
read(sockfd, &server_msg, 200);
//check ok velidity from server
if(strcmp(server_msg, ok) != 0 ) {
errno++;
perror("Incorrect security phrase");
close(sockfd);
exit(1);
}
//? dup2 STDIN_FILENO = server socket fd?
//dup2(sockfd, STDIN_FILENO);
//begin while(1)///////////////////////////////////////
while(1){
//memset both msg arrays
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(server_msg));
//print Enter Command, scan input, fflush to stdout
printf("<<Enter Command>> ");
scanf("%s", client_msg);
fflush(stdout);
//check quit input, if true close and exit successfully
if(strcmp(client_msg, "quit") == 0) {
printf("Exiting\n");
close(sockfd);
exit(EXIT_SUCCESS);
}
//write command to server
write(sockfd, command, strlen(command));
//read ready from server
read(sockfd, &server_msg, 200);
//check ready validity from server
if(strcmp(server_msg, ready) != 0) {
errno++;
perror("Failed Server Communications");
close(sockfd);
exit(1);
}
//memset server_msg
memset(&server_msg, 0, sizeof(server_msg));
//begin looping and retrieving from stdin,
//break loop at EOF or complete
while((read(sockfd, server_msg, 200) != 0) && (strcmp(server_msg, complete) != 0)) {
//while((fgets(server_msg, 4096, stdin) != EOF) || (strcmp(server_msg, complete) == 0)) {
printf("%s", server_msg);
memset(&server_msg, 0, sizeof(server_msg));
}
}
}
The output of subprocess, spawned by system(), is not connected to the calling parent process.
Try popen().
In the server, the error exits from handle_client() carefully call close(connect_fd); but the ordinary exit does not. This means that the server does not close the connection to the client, so the client waits for the server to disconnect. This is why you see the code hanging.

NETworking with UDP

what happens when a UDP packet is sent to a host using sendto().
all the bits i am sending are sent(known from the return value).immediately i use a recvfrom() which does not output anything but program do not exit(i.e no return value).
I think that the program must exit if no reply is recieved.
what will the replies for a UDP packet from a port.
is this packet blocked by firewall?? if yes then why is the return value of sendto is non-negative.
recvfrom() will block until a message is received unless you set the socket to non-blocking.
The interfaces you want to look for are
ioctl() with FIONBIO or O_NONBLOCK (depending your platform),
select() to wait for data to arrive, or timeout after a while
Also remember that the address and port number for sendto() usually be network-byte order, so look into ntohl and ntohs.
you must have some error in your client or server. try localhost first, so you avoid firewall problems
this is an example of nonblocking udp client/server I was using for my tests, it uses ioctl() to check if there is data to read on the socket, however if you want to do some serious application using epoll would be more efficient also you can specify timeout to wait in microseconds:
[null#localhost tests]$ cat udpserv.c
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.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>
#include <errno.h>
#define BUFLEN 512
#define NPACK 15
#define PORT 9930
void diep(char *s)
{
printf("erno=%d errstr=%s\n",errno,strerror(errno));
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s,ret,nbytes, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr*) &si_me, sizeof(si_me))==-1)
diep("bind");
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK);
sleep(10);
for (i=0; i<NPACK; i++) {
ret=ioctl(s,FIONREAD,&nbytes);
if (ret==-1) {
printf("error on FIONREAD\n");
} else {
printf("nbytes=%d\n",nbytes);
}
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, &slen)==-1)
diep("recvfrom()");
printf("Received first half of packet from %s:%d\nData: %s\n\n",
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
close(s);
return 0;
}
[null#localhost tests]$ cat udpclient.c
#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 SRV_IP "127.0.0.1"
#define BUFLEN 200
#define NPACK 10
#define PORT 9930
/* diep(), #includes and #defines like in the server */
void diep(char *s)
{
perror(s);
exit(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;
}
the sendto() is non negative because it returns number of bytes sent. check the man page for sendto

How can I send a datagram with an Ethernet trailer?

How can I send a datagram with an Ethernet trailer? If I use SocketType.Raw, I'll have to send the whole IP header and I have no idea how to do that.
Something like this perhaps?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <sys/ioctl.h>
int s;
unsigned char buffer[513];
struct sockaddr_ll socket_address;
int main ( void )
{
unsigned char seq;
unsigned int ra;
int length;
struct ifreq ifr;
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1)
{
printf("error creating socket\n");
return(1);
}
memset(&ifr,0, sizeof(struct ifreq));
strncpy(ifr.ifr_name,"eth0",IFNAMSIZ);
if(ioctl(s, SIOCGIFINDEX, &ifr) < 0)
{
perror("ioctl SIOCGIFINDEX");
exit(1);
}
printf("index %d\n",ifr.ifr_ifindex);
printf("socket created\n");
memset(&socket_address,0,sizeof(socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ALL);
socket_address.sll_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)(&socket_address), sizeof(socket_address)) < 0)
{
perror("bind error");
exit(1);
}
printf("bound\n");
length=27;
memset(buffer,0,sizeof(buffer));
//destination
buffer[ 0]=0xFF;
buffer[ 1]=0xFF;
buffer[ 2]=0xFF;
buffer[ 3]=0xFF;
buffer[ 4]=0xFF;
buffer[ 5]=0xFF;
//source
buffer[ 6]=0x00;
buffer[ 7]=0x19;
buffer[ 8]=0xd1;
buffer[ 9]=0x02;
buffer[10]=0xdc;
buffer[11]=0xb3;
//length
buffer[12]=((length-14)>>8)&0xFF;
buffer[13]=((length-14)>>0)&0xFF;
//payload
buffer[14]=0x12;
buffer[15]=0x34;
for(ra=0;ra<20;ra++)
{
buffer[16]=ra;
if(send(s,buffer,length,0) < 0 )
{
printf("sendto failed\n");
break;
}
else
{
printf("sent\n");
}
}
close(s);
return(1);
}
That should give a raw packet that you can see on wireshark. if you want to have the ip eader, or make it a udp or something like that you can use this method and build the header yourself (it is trivial look at the rfcs or just use wireshark to look at a bunch of other packet headers). Note that for udp you do not have to compute a checksum 0x0000 is a valid checksum that is supposed to pass on through.
If all you want is a udp packet with zeros at the end that is somewhat the same, probably easier, let me know.
That trailer is used to pad ethernet frames to their minimum length (46 bytes of payload). So send a small UDP packet - smaller than 18 bytes (as IP + UDP is normally 28 bytes)

Resources