Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
This is a section of the server code. When the client exits, the server program dies without coring after the following line:
n = send(s, buf+total, bytesleft, 0);
Here is the function:
static ssize_t conn_Send(int s, u8* buf, ssize_t len)
{
ssize_t total = 0; // how many bytes we've sent
ssize_t bytesleft = len; // how many we have left to send
ssize_t n;
while(total < len)
{
n = send(s, buf+total, bytesleft, 0);
//abort();
if (n < 0)
{
return n;
}
total += n;
bytesleft -= n;
}
return total;
}
I have looked in the obvious places: /proc/sys/kernel/core_pattern is set correctly, and indeed the program exits with a core file if the "//abort();" is commented out above.
Any ideas? I'm at wit's end.
When the client exits, the server program dies
n = send(s, buf+total, bytesleft, 0);
This is typically the result of getting killed by SIGPIPE when the other end closes the connection. There are quite a few ways to getting around this, including:
You can use setsockopt with SO_NOSIGPIPE
You can use MSG_NOSIGNAL as a send flag
You can ignore SIGPIPE
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
The scenario is like this: one process is using epoll on several sockets, all sockets are set non-blocking and edge triggered; then EPOLLIN event occurs on one socket, then we start to read data on its fd, but the problem is that there are too many data coming in, and in the while loop reading data, the return value of recv is always larger than 0. So the application is stuck there, reading data and cannot move on.
Any idea how should I deal with this?
constexpr int max_events = 10;
constexpr int buf_len = 8192;
....
epoll_event events[max_events];
char buf[buf_len];
int n;
auto fd_num = epoll_wait(...);
for(auto i = 0; i < fd_num; i++) {
if(events[i].events & EPOLLIN) {
for(;;) {
n = ::read(events[i].data.fd, buf, sizeof(buf));
if (errno == EAGAIN)
break;
if (n <= 0)
{
on_disconnect_(events[i].data.fd);
break;
}
else
{
on_data_(events[i].data.fd, buf, n);
}
}
}
}
When using edge triggered mode the data must be read in one recv call, otherwise it risks starving other sockets. This issue has been written about in numerous blogs, e.g. Epoll is fundamentally broken.
Make sure that your user-space receive buffer is at least the same size as the kernel receive socket buffer. This way you read the entire kernel buffer in one recv call.
Also, you can process ready sockets in a round-robin fashion, so that the control flow does not get stuck in recv loop for one socket. That works best with the user-space receive buffer being of the same size as the kernel one. E.g.:
auto n = epoll_wait(...);
for(int dry = 0; dry < n;) {
for(auto i = 0; i < n; i++) {
if(events[i].events & EPOLLIN) {
// Do only one read call for each ready socket
// before moving to the next ready socket.
auto r = recv(...);
if(-1 == r) {
if(EAGAIN == errno) {
events[i].events ^= EPOLLIN;
++dry;
}
else
; // Handle error.
}
else if(!r){
// Process client disconnect.
}
else {
// Process data received so far.
}
}
}
}
This version can be further improved to avoid scanning the entire events array on each iteration.
In you original post do {} while(n > 0); is incorrect and it leads to an endless loop. I assume it is a typo.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm trying to close socket on windows from closesocket(), but it takes 20 sec to complete. at first I thought it was about linger interval, although I was not setting anything with setsockopt by linger, so I added such code:
linjer lobj;
lobj.l_onoff = 1;
lobj.l_linger = 0;
sz = sizeof(lobj);
setsockopt(s_, SOL_SOCKET, SO_LINGER, (char *) &lobj, sz);
but it still does not help.
any ideas? I just want to close connection, doesnt matter if its gracefull or abortion, just want to close it as soon as possible.
P.S. it takes exactly 20 sec.
lobj.l_onoff = 1;
lobj.l_linger = 0;
sz = sizeof(lobj);
setsockopt(s_, SOL_SOCKET, SO_LINGER, (char *) &lobj, sz);
lobj.l_onoff = -1;
lobj.l_linger = -1;
getsockopt(s_, SOL_SOCKET, SO_LINGER, (char *) &lobj, &sz);
log << "Option 1:" << lobj.l_linger << ".\n";
log << "Option 2:" << lobj.l_onoff << ".\n";
closesocket(s_);
this code prints option1 = 0 and option2 = 1, so it really sets option correctly.
Also, observing from wireshark, it sends RST at the beginning of whole delay.
plus, closesocket() returns 0.
P.S. I have set SO_REUSADDR, can it be causing it?
If you can't post the code you can't ask the question here. Those are the rules.
However the only way closesocket() can take any measurable time at all is if:
there is a lot of pending outgoing data, and
you have set a positive SO_LINGER timeout.
You can only get a delay of 20 seconds by setting a positive SO_LINGER timeout of >= 20 seconds and having a lot of pending outgoing data and probably a peer that isn't reading.
If you had left SO_LINGER strictly alone, which you should, or set it to false, or true with a zero timeout, closesocket() is asynchronous and returns immediately, and in the latter case you would also have reset the connection.
Ergo either you haven't done what you claimed or your observations are faulty. Possibly it is the final send() which is blocking.
It would be interesting to know whether this closesocket() call returned -1 and if so what the error value was.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I need quick advice for this code it does not compile and i cant figure out whats wrong with it. I am just trying to print the elements in the array in PORT C which is my output port. Thanks
#include <htc.h>
#define _XTAL_FREQ 500000
void main()
{
int x[8]={0b1110, 0b1010, 0b1000, 0b1001, 0b0001, 0b0101, 0b0111, 0b0110, 0b1110};
int i,PORTC;
TRISC = 0 ; // set PORTC as OUTPUT
PORTC = 0b0000;
for(;;){ // forever
for ( i = 0; i < 8; i++ ){
PORTC = n[ i ] = i + 1; /* set element at location i to i + 1 */
__delay_ms(500); }
}
}
You reference n[ i ], when you apparently mean x[ i ].
You really shouldn't declare PORTC as a local int, it's supposed to be a special "variable" that mirrors the hardware register. You might need some processor-specific include(s) too, not sure.
In the absence of someone who actually knows something about the PIC, I suggest you try something like this:
void main() {
int x[8]={0b1110, 0b1010, 0b1000, 0b1001, 0b0001, 0b0101, 0b0111, 0b0110, 0b1110};
int i;
TRISC = 0;
PORTC = 0b0000;
for(;;) {
for (i = 0; i < 8; i++) {
PORTC = x[i];
__delay_ms(500); }
}
}
}
TRISC is the control port for PORTC. A value of zero sets all pins on PORTC to be output ports. [thanks - see comment]
PORTC is an input/output port. I assume it's hooked up to a display of some kind. With the proper setting of TRISC it should act as an output port.
This should output 8 values at half-second intervals from the table to the port and repeat forever. Kind of "hello world" for microprocessors.
I have a simple tcp/ip server written in c++ on linux. I'm using asynchronous sockets and epoll. Is it possible to find out how many bytes are available for reading, when i get the EPOLLIN event?
From man 7 tcp:
int value;
error = ioctl(sock, FIONREAD, &value);
Or alternatively SIOCINQ, which is a synonym of FIONREAD.
Anyway, I'd recommend just to use recv in non-blocking mode in a loop until it returns EWOULDBLOCK.
UPDATE:
From your comments below I think that this is not the appropriate solution for your problem.
Imagine that your header is 8 bytes and you receive just 4; then your poll/select will return EPOLLIN, you will check the FIONREAD, see that the header is not yet complete and wayt for more bytes. But these bytes never arrive, so you keep on getting EPOLLIN on every call to poll/select and you have a no-op busy-loop. That is, poll/select are level-triggered. Not that an edge triggered function solves your problem either.
At the end you are far better doing a bit of work, adding a buffer per connection, and queuing the bytes until you have enough. It is not as difficult as it seems and it works far better. For example, something like that:
struct ConnectionData
{
int sck;
std::vector<uint8_t> buffer;
size_t offset, pending;
};
void OnPollIn(ConnectionData *d)
{
int res = recv(d->sck, d->buffer.data() + offset, d->pending);
if (res < 0)
handle_error();
d->offset += res;
d->pending -= res;
if (d->pending == 0)
DoSomethingUseful(d);
}
And whenever you want to get a number of bytes:
void PrepareToRecv(ConnectionData *d, size_t size)
{
d->buffer.resize(size);
d->offset = 0;
d->pending = size;
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm having some strange things happen with my program, and I'm not sure what I should be doing. This is a pseudocode version of what my code looks like so far:
Server:
//Set up Server sockets
int maximum;
// Collect the maximum
cout << "\nEnter a Maximum:";
cin >> maximum;
cout << "\n";
int *array = new int[maximum + 1];
memset(array, 0, sizeof(array));
while(array[0] < anInt){
//receive the array from the client
if(recv(newsockfd, array, maximum, 0) < 0){
perror("ERROR receiving from socket");
}
mathFunction(array); //A function that alters the contents of array
array[0]++;
//If array[0] isn't too big
if(array[0] < anInt){
// Send the array to the client
if(send(newsockfd, array, maximum, 0) < 0){
perror("ERROR sending to socket");
}
}
}
Client:
//Set up Client sockets
//The maximum was already sent over earlier
int *array = new int[maximum + 1];
while(array[0] < anInt){
//receive the array from the server
if(recv(sockfd, array, maximum, 0) < 0){
perror("ERROR receiving from socket");
}
mathFunction(array); //A function that alters the contents of array
array[0]++;
if(send(sockfd, array, maximum, 0) < 0){
perror("ERROR sending to socket");
}
}
My problem is that I keep getting a "Connection reset by peer" error, which leads to a Segmentation Fault, crashing my program. Also, when playing around with the 3rd argument of the send/recv functions (currently set as maximum), my program acts differently. It will actually work perfectly if the user enters a maximum of 100, but anything more than that screws it up.
I know this is a long shot, but can anyone see something that I'm doing wrong?
First of all code that posted by you has a logical error:
Server first receive data from the client, do something with it and then send its result back to the client.
In the other side client also receive data from server, do something with it and then send it back to the server.
And that's obviously a race condition, no one send data to other side to begin communication.
Beside that logical error you have some C++ errors:
1) memset(array, 0, sizeof(array)) only 0 initialize sizeof(int*) bytes from your array not entire array, since sizeof(array) is always sizeof(int*) if you want to 0 initialize entire array (and I think you want it) you should call:
memset(array, 0, (maximum + 1) * sizeof(int));
or even better:
std::fill( array, array + maximum + 1, 0 );
And in C++ it is much better to use classes like std::vector instead of raw pointers:
std::vector<int> array( maximum + 1 ); // automatically initialize to 0
2) Your array type is int* and send/recv count its input by byte, so if you want to send/recv entire array you must have something like:
send(sockfd, (char*)array, maximum * sizeof(int), 0);
3) You should check return value of send/recv, specially recv since it may recv less data in each call, for example you send 8K data and recv only receive first 1K and rest of it remain in the network buffer, so you should call it repeatedly until you read your buffer completely.
One thing that seems obviously incorrect is:
mathFunction(array);
doesn't tell mathFunction() how many elements are in the array. In fact, you throw away this information when you call recv() by not storing it anywhere (all your code does is check to see if it's less than zero, but doesn't use it if it is positive). When calling recv(), your code must be prepared to receive any number of bytes from 1 through maximum. If you don't get all the bytes you ask for, then you need to call recv() again to get more.