i am writing socket programming at server side.
size=recv(src_port,buffer,256,0);
printf("%d \n",buffer[0]);
printf("The message the server recieved %s \n",buffer);
if(size==-1){
printf("The server is unable to recieve message from client%d\n",src_port);
return 0;
}
else if(size==0){
printf("The server is recieving 0 byts messgae from client%d\n",src_port);
return 0;
}
else{
if(send(cl_port,buffer,256,0)==-1){
printf("unable to send from client%d\n",src_port);
return 0;
}
return 1;
}
the first character is 0 i.e its is null.
why is it that the input buffer is zero ??
Does there any reasons like that the memory of buffer is not accessible??
Related
I have been trying to receive and process the packets from tunnel. There are separate blocks for processing v4 and v6 packets. If the packet does not fall under the either of the categories, they will be dropped. For me, every packets are being dropped during execution. When I used wireshark to capture the packets from the tunnel, I noticed the difference in packet size, i.e., length of the packet. For example, when the length of a received packet in Wireshark is 60 whereas the program prints it 64 as length. I noticed the 4 bytes difference in all packets. I am unable to find out, what I am doing wrong here? Would anyone help me. I also attached the screen of wireshark and program execution for perusal.
Image: Captured packets from tunnel through wireshark and program
#define MTU 1600
void processPacket(const uint8_t *packet, const size_t len) {
//1st octet identifies the IP version
uint8_t version = (*packet) >> 4;
//...
printf("IP version - %d\n", version);
if (version == 4 ) {
//ipv4 packet process ...
} else if (version == 6) {
//ipv6 packet process ...
} else {
//drop packet
printf("Unknown IP version, drop packet\n");
}
}
int main() {
struct ifreq ifr;
int fd;
uint8_t *buffer = (uint8_t *)(malloc(MTU));
ssize_t len;
if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
perror("Unable to open /dev/net/tun");
exit(EXIT_FAILURE);
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, "tun0", IFNAMSIZ);
if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
perror("Error encountered during ioctl TUNSETIFF");
close(fd);
exit(EXIT_FAILURE);
}
printf("Device tun0 opened\n");
while(1) {
len = read(fd, buffer, MTU);
printf("Read %lu bytes from tun0\n", len);
processPacket(buffer, len);
}
printf("\nPress any key to exit...");
getchar();
close(fd);
}
The tunnel device pre-pends the IP packet with additional information, so the first byte is not the IP version. If you don't need it, you can add IFF_NO_PI to ifr_flags. See kernel documentation.
I'm currently having an issue with pop3 server which is based on select() function. Basically server holds multiple clients at once, but Welcome message sends as many times as is the number of connected client.
This is an example of messages sent to clients.
//file descriptor, array of clients
fd_set readset;
int sock_arr[30];
int max_fd, rc;
servsock = socket(AF_INET, SOCK_STREAM, 0);
/*...*/
max_fd = servsock;
do
{
FD_ZERO(&readset);
FD_SET(servsock, &readset);
for (int i = 0; i < 30; i++) {
rc = sock_arr[i];
if (rc > 0)
FD_SET(rc, &readset);
if (rc > max_fd)
max_fd = rc;
}
activity = select(max_fd + 1, &readset, NULL, NULL, &timeout);
if (activity < 0)
{
perror(" select() failed");
break;
}
if (activity == 0)
{
printf(" select() timed out. End program.\n");
break;
}
Message is sent as many times as is the number of connected client e.g.
if first client is connected the message is sent once
if second client is connected the message is sent twice etc.
//here server accepts new connections
if (FD_ISSET(servsock, &readset)) {
serv_socket_len = sizeof(addr);
peersoc = accept(servsock,(struct sockaddr *) &addr, &serv_socket_len);
if (peersoc < 0) {
error("Accept failed!\n", ERR_SCK);
}
else {
char message[256];
strcat(message, reply_code[1]);
strcat(message, reply_code[3]);
strcat(message, reply_code[0]);
//Welcome message
send(peersoc, message, strlen(message), 0);
for (int i = 0; i < 30; i++) {
if (sock_arr[i] == 0) {
sock_arr[i] = peersoc;
break;
}
}
}
}
//server processing input messages from clients using threads
/*...*/
I have no idea what causes I assume something with file descriptors. Please give me some advice if possible.
Solved I have forgotten to clear buffer for sending message
...
char message[256];
memset(message, 0, sizeof(message));
...
For some reason FD_ISSET always returns true for &wfds, even when there is nothing to send. Here is the code snippet (same on both client and server). Both client and server get same issue with select saying wfds is on. Shouldn't it only activate when i type a message on my keyboard and press enter?
while (1) {
//trying select..
tv.tv_sec = 29;
tv.tv_usec = 500000;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(new_sockfd, &rfds);
FD_SET(new_sockfd, &wfds);
n = select(new_sockfd + 1, &rfds, &wfds, NULL, &tv);
if (n > 0) {
if (FD_ISSET(new_sockfd, &rfds)) {
while (1) {
if ((num = recv(new_sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
}
//this always returns true on client and host
if (FD_ISSET(new_sockfd, &wfds)) {
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(new_sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(new_sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
}
}
}
You probably misunderstood how writefds parameter works for select().
You should set the flag in writefds for your file descriptor before calling select() if and only if you have something to send.
Then select() returns with the flag left set in writefds, when the socket has enough space in the socket buffers to accept data for sending. Then you check for that flag, and realize that the socket is available for sending, and you also know that you have something to send, since originally it was you, who set the flag before calling select(). Therefore you can proceed with sending the data over the socket. Then, if you have sent all data you have, and your to-be-sent buffers are empty, you keep the flag for writefds cleared when next time you call select().
I'm trying to send a list of 600 records over TCP/IP sockets using a java server and a Blackberry client. But every time it reaches the 63th record it stops, the odd thing about this is that if I only send 200 records they are sent ok.
I haven't been able to understand why it happens, only that 63 records equals aprox to 4kB, basically it sends:
an integer with the total number of records to be sent
And for every record
an integer with the length of the string
the string
a string terminator "$$$"
Since i need to send the whole 600 i have tried to close the InputStreamReader and reopen it, also reset it but without any result.
Does anybody else have experienced this behaviour? thanks in advanced.
EDIT
Here the code that receives:
private String readfromserver() throws IOException {
int len=_in.read(); // receives the string length
if (len==0) // if len=0 then the string was empty
return "";
else {
char[] input = new char[len+1];
for (int i = 0; i < len; ++i)
input[i] = (char)_in.read();
StringBuffer s = new StringBuffer();
s.append(input);
return s.toString();
}
}
private void startRec(String data) throws IOException
{
boolean mustcontinue=true;
int len=_in.read(); // read how many records is about to receive
if (len==0) {
scr.writelog("There is no data to receive");
}
else {
for(int i=0; i<len; i++)
if (mustcontinue) {
mustcontinue=mustcontinue && showdata(readfromserver());
}
else {
scr.writelog("Inconsistency error #19");
}
}
}
the function showdata only shows the received string in a LabelField.
The code in the server:
try {
_out.write(smultiple.size()); // send the number of records
_out.flush();
for (int x=0; x<smultiple.size(); x++)
{
int l=smultiple.elementAt(x).length();
_out.write(l); // send string length
if (l>0)
_out.write(smultiple.elementAt(x)); // send string
}
_out.flush();
} catch (Exception e) {
principal.dblog(e.toString());
}
smultiple is a vector containing the strings and everyone already have the terminator $$$.
Thanks.
I think 200 goes fine and 600 -not, because the latter number is bigger than 255 :-) Your code
int len=_in.read();
probably reads a byte and not an integer (4 bytes)
I am implementing a communication between 2 processes using a queue. The problem is that when I call the function mq_receive, I get this error: Message too long.
I have done the following:
struct mq_attr attr;
long size = attr.mq_msgsize;
.... // initializing the queue "/gateway"
int rc = mq_receive(gateway, buffer, size, &prio);
If I print the size value, I get size=1, while when I print the same size but from another program (got by the same mechanism), I get something not long integer ( -1217186280 )...
How can I solve this error?....so while size = 1, I believe it's right to say "message too long" but why is 1?
P.S. I have also tried to put :
int rc = mq_receive(gateway, buffer, sizeof(buffer), &prio);
but with no result.
It seems like you need to read the docs more carefully. When you call mq_receive you should pass size of the destination buffer. This size must be greater than the mq_msgsize attribute of the queue. In addition, it seems like you have an error in queue attributes initialisation that makes proper mq_receive call impossible. Here is standard message queue session:
Fill mq_attr struct (doc):
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 33;
attr.mq_curmsgs = 0;
Create queue with mq_open in master process (doc):
mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr);
In writer process open queue for writing:
mqd_t queue = mq_open(qname, O_WRONLY);
And send some text. Length of the text must be lesser than mq_msgsize attribute of the queue (doc):
mq_send(queue, "some message", strlen("some message")+1, 1);
In reader process open queue for reading:
mqd_t queue = mq_open(qname, O_RDONLY);
And then allocate buffer and receive message. Size of buffer *must be greater than the mq_msgsize attribute of the queue. Here we create 50-byte buffer while mq_msgsize == 33 (doc):
char rcvmsg[50];
int iret = mq_receive(queue, rcvmsg, 50, NULL);
Also remember that you should use %ld for print long instead of %d.
When debugging realtime POSIX queues, you should start with a sample program which works and go forward from there. Once you have the sample program running, it should be a simple matter of ensuring that your own code follows all the steps.
The following program has been tested successfully under Ubuntu 11.04:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>
#define MQNAME "/pax"
#define MQMESG "Hello there!"
static mqd_t serverUp (void) {
int rc;
mqd_t svrHndl;
struct mq_attr mqAttr;
printf ("Bringing up server.\n");
rc = mq_unlink (MQNAME);
if (rc < 0) {
printf (" Warning %d (%s) on server mq_unlink.\n",
errno, strerror (errno));
}
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 1024;
svrHndl = mq_open (MQNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR, &mqAttr);
if (svrHndl < 0) {
printf (" Error %d (%s) on server mq_open.\n",
errno, strerror (errno));
exit (1);
}
printf (" Server opened mqd_t of %d.\n", svrHndl);
return svrHndl;
}
static void serverReceive (mqd_t svrHndl) {
int rc;
char buffer[2048];
printf ("Server receiving on mqd_t %d.\n", svrHndl);
rc = mq_receive (svrHndl, buffer, sizeof (buffer), NULL);
if (rc < 0) {
printf (" Error %d (%s) on server mq_receive.\n",
errno, strerror (errno));
exit (1);
}
printf (" Received [%s].\n", buffer);
}
static void serverDown (mqd_t svrHndl) {
printf ("Bringing down server with mqd_t %d.\n", svrHndl);
mq_close (svrHndl);
}
static void clientSend (void) {
mqd_t cliHndl;
int rc;
printf ("Client sending.\n");
cliHndl = mq_open (MQNAME, O_RDWR);
if (cliHndl < 0) {
printf (" Error %d (%s) on client mq_open.\n",
errno, strerror (errno));
exit (1);
}
printf (" Client opened mqd_t of %d.\n", cliHndl);
rc = mq_send (cliHndl, MQMESG, sizeof (MQMESG), 1);
if (rc < 0) {
printf (" Error %d (%s) on client mq_send.\n",
errno, strerror (errno));
exit (1);
}
mq_close (cliHndl);
}
int main (void) {
mqd_t svrHndl;
svrHndl = serverUp ();
clientSend ();
serverReceive (svrHndl);
serverDown (svrHndl);
return 0;
}
The output on my system is:
Bringing up server.
Server opened mqd_t of 3.
Client sending.
Client opened mqd_t of 4.
Server receiving on mqd_t 3.
Received [Hello there!].
Bringing down server with mqd_t 3.
Don't forget to unlink the message queue before running your program again. If you dont unlink it, it will still use the old message queue settings. This happens when you end your program with Ctrl+C. I think it is a good idea to put the following code at the beginning of the program:
if(mq_unlink(QUEUENAME) == 0)
fprintf(stdout, "Message queue %s removed from system.\n", QUEUENAME);
An alternative form (C++ style) that checks for real errors (like permissions) and ignores the cases where the queue already exists or not:
int rc = mq_unlink(name.c_str());
if (rc != 0 && errno != ENOENT)
THROW_ERRNO_EXCEPTION();
// ENOENT is the status code if the queue doesn't exist, which is not an error
// if you are immediately going to create it.
Just a correction above...
"This size must be equal or greater than the mq_msgsize attribute of the queue"
Equal size is probably required if you are passing a struct instead of a buffer:
see: send struct in mq_send