I'm working on an application that opens a data stream TCP socket to another.
After the connection is open and accepted by the server, I send a "login" message which is received by the server successfully, the server attempts to send a "success" message. This is where things get weird.
The write on the server fails and errno is set to "Broken pipe".
The client polls on the file descriptor waiting for data to read which fails as well. On it errno is set to "Connection refused".
All connections are TCP on the loopback device.
Using tcpdump, I can see that FIN is send from the client to the server.
It can be found here.
How can errno be "Connection refused" if the connection was already established?
What might cause this behavior? The client code is synchronous without any threads and no one else has access to the file descriptor.
If it matters, the server is the Asterisk manager.
Snippets of the client code (real code has error checking, separated functions and such):
struct sockaddr_in sa;
int fd;
fd = sock_socket(SOCK_STREAM, 0, 0);.
MZERO(sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
sa.sin_port = htons(MANAGER_PORT);
connect(fd, (struct sockaddr *)&sa, sizeof(sa));
sprintf(buf,
"Action: Login\r\n"
"Username: %s\r\n"
"Secret: %s\r\n"
"Events: %s\r\n"
"ActionID: %d\r\n"
"\r\n",
MANAGER_USERNAME, MANAGER_PASSWORD, events, manager_action_id++)
write(fd, buf, strlen(buf));
{
struct pollfd fds = {fd, POLLIN, 0};
if (poll(&fds, 1, timeout) <= 0)
return -1; /* This is where the client fails with "Connection refused" */
}
Thanks!
P.S. - Sorry for responding to comments inside the question itself, but I created the question before I created an account and I'm not allowed to add comments.
Regarding to "Broken Pipe",i guess you are trying to write some stuff in a closed socket so a SIG_PIPE signal is released,in this case.Declare <signal.h> and install signal operations in a manner of,like signal(SIG_PIPE,SIG_IGN)
Related
Just for the purpose of learning raw sockets in C I am writing a simple server that uses raw sockets to receive and send messages.
I create the socket
if ((r_sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP))< 0){
perror("socket");
exit(-1);
}
Then I create an infinite loop and start receiving, processing, and replying
while(1){
if((n = recvfrom(r_sock, buffer, BUFLEN, 0, (struct sockaddr *) &client, &client_len))<0){
perror("recvfrom");
exit(-1);
}
// Discard messages not intended to the server
if(htons(udp->uh_dport) != my_port){
continue;
}
//Do whatever with the data received and then send reply to client
// ....
if((n = sendto(r_sock, udp, ntohs(udp->uh_len), 0, (struct sockaddr *) &client, client_len))<0){
perror("sendto");
exit(-1);
}
}
I am not showing here the definition of every single variable but for the sake of completeness, buffer is a char array of size BUFLEN (big enough) and udp is a struct udphdr pointer to the right position in the buffer.
The point is that I have another program that serves as client using standard UDP sockets (SOCK_DGRAM) which is proved to be working properly (I also tried with netcat just in case). When I send a message with the client, it never receives the reply back. It seems that when the server sends the reply to the client, the server itself gets the message and the client gets nothing.
So, my question is: is there a way of solving this with raw sockets? That is, to make the server not receive its own messages and preventing others from receiving them?
Thanks in advance!
I have just realised that it was a problem with the checksum... Once I had a correct checksum in UDP the packet was correctly received by the client.
Wireshark gave me the lead to the solution. I saw that the checksum was not validated so I went to Edit > Preferences > Protocols > UDP > Validate the UDP checksum if possible and checked it.
Hope it helps
This question already has answers here:
Detecting TCP Client Disconnect
(9 answers)
Closed 4 years ago.
I have basic tcp application written in C. It basically sends data to a tcp server. I have connected two PC's with cross cable. I send data from one, and successfully get this data from another one. I have built this mechanism to test If somehow connection broken by unhealty ways (ruptured cable etc.), I want to be informed as client. But things doesn't work as I wanted.If I manually stop tcpserver, client side is informed, but when I start program, connection establishes, data starts to flow, then I unplug the cable, and both sides behaves like nothing happened. Client still sends data with no error, and server still shows the client connected but data flow stops. After a few minutes, I plug cable again, the datas -which considered as sent but not sent- flushes suddenly then program continues normally. How can I detect a broken connection like this? Any help would be appreciated. Here is the code;
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
int main() {
const char* server_name = "192.168.5.2";
const int server_port = 30152;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// creates binary representation of server name
// and stores it as sin_addr
// http://beej.us/guide/bgnet/output/html/multipage/inet_ntopman.html
inet_pton(AF_INET, server_name, &server_address.sin_addr);
// htons: port in network order format
server_address.sin_port = htons(server_port);
// open a stream socket
int sock;
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// TCP is connection oriented, a reliable connection
// **must** be established before any data is exchanged
if (connect(sock, (struct sockaddr*)&server_address,
sizeof(server_address)) < 0) {
printf("could not connect to server\n");
return 1;
}
// send
// data that will be sent to the server
const char* data_to_send = "HELLO THIS IS DATA!";
while(1)
{
int err = send(sock, data_to_send, strlen(data_to_send), 0);
if(err==-1)
{
printf("ERROR \n");
break;
}
else
{
printf("sent \n");
sleep(1);
}
}
printf("EOP\n");
// close the socket
close(sock);
return 0;
}
If the peer of a TCP connection closes the connection, it will lead to a recv call on your end to return 0. That's the way to detect closed (but not broken) connections.
If you don't currently receive anything from the peer, you need to make up a protocol on top of TCP which includes receiving data.
Furthermore, sending might not detect broken connections (like missing cables etc.) directly, as there are a lot of retransmissions and timeouts. The best way is again to implement some kind of protocol overlaying TCP, one that for example contains a kind of "are you there" message which expects a reply. If a reply to the "are you there" message isn't received within some specific timeout, then consider the connection broken and disconnect.
I developed an application which contains a small http server.
my application is launched in the boot. if the application is stopped normally (etc/init.d/myappli stop) the socket will be closed
close (socket_desc);
but if I kill it with kill -9 the socket will not be closed
http server code :
void http_server_init(void)
{
struct sockaddr_in server;
int cr_port;
for(;;) {
cr_port = conf.port;
int i = (DEFAULT_PORT == cr_port)? 1 : 0;
//Create socket
cr_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (cr_socket_desc == -1)
{
LOG (ERROR,"Could not open server socket, Error no is : %d, Error description is : %s", errno, strerror(errno));
sleep(1);
continue;
}
/* enable SO_REUSEADDR */
int reusaddr = 1;
if (setsockopt(cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) {
LOG (WARNING,"setsockopt(SO_REUSEADDR) failed");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
for(;;i++) {
server.sin_port = htons(cr_port);
//Bind
if( bind(cr_socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
LOG (ERROR,"Could not bind server socket on the port %d, Error no is : %d, Error description is : %s", cr_port, errno, strerror(errno));
cr_port = DEFAULT_PORT + i;
LOG (INFO,"Trying to use another port: %d", cr_port);
continue;
}
break;
}
break;
}
LOG (INFO,"server initiated with the port: %d", cr_port);
}
Questions:
1) How to close socket if the program was killed?
2)And what is the type of socket should be used in this case to avoid that the socket will not be used by another process using tcp socket?
If you kill a program with kill -9 the port will be closed, not by the program, but by the operating system. The fact it is being closed is precisely what is making it available for being taken over by another process.
Ports are not 'reserved' for particular programs. The only reservation of ports after the death of the program is if you don't set SO_REUSEADDR in which case it's reserved for (from memory) 2 TIME_WAIT periods. But you've told us in the comments you do set SO_REUSEADDR. What that means is 'make the port available to the next program that tries to listen on it'. It doesn't differentiate between that program being the same program or a different one.
I think you think that SO_REUSEADDR means 'this program may want to reuse the port so don't give it to anyone else'. That is categorically not what SO_REUSEADDR does. SO_REUSEADDR (broadly speaking, and on Unix anyway) releases the port for use by any program to the operating system immediately after your program dies, as opposed to waiting for a while. On MS it is (somewhat bizarrely) used to bind to a port that's already in use. For more information, see Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems? - however note that on no operating system does it mean what I'm guessing you think it means.
Your problem is that the old socket will be in TIME_WAIT state a short while before it is released.
If you want to reduce the time spent in the TIME_WAIT state you can reduce the linger time. Note that there are risks attached to reducing it too much.
You can change the linger time for your socket using setsockopt(2).
Related links:
The ultimate SO_LINGER page
TCP option SO_LINGER (zero)
I've been trying to write a POP3 client for yahoo, but whenever I send a valid command, I cannot read from socket . I know it's not safe to create applications that deal in plaintext over the web, but I'm just trying to learn more about POP3 for now.
I'm creating a graphic interface using QT , but I believe this is irrelevant for now.
First of all, I made sure that yahoo supports plaintext communication by running simple commands in the terminal:
telnet pop.mail.yahoo.com 110
+OK hello from popgate-0.8.0.504347 pop011.mail.ir2.yahoo.com
user validuser
+OK password required.
pass validpassword
+OK maildrop ready, 100 messages (134513 octets) (13531)
This is how I handle opening the connection:
int openConnection(char ip[], int port)
{
//descriptor of socket
int sd;
struct sockaddr_in server;
//fill in server structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr (ip);
server.sin_port = htons (port);
//create communication socket
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
//if cannot create, return error
return -2;
}
if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
{
return -1;
}
return sd;
//values to be returned
//-2 - could not create socket
//-1 - could not connect to server
//socket descriptor in case of success
}
I get no problem with creating the socket and connecting when I call
int sd = openConnection ("188.125.68.106", 110)
(188.125.68.106 = ip of pop.mail.yahoo.com)
I can even read the welcoming message without using select or epoll.
char message[80];
read (sd, message, 80);
Message:
+OK hello from popgate-0.8.0.504347 pop011.mail.ir2.yahoo.com
I can also send all sorts of invalid commands, and read the error returned
int sd = openConnection ("188.125.68.106", 110)
write (sd,"this command is invalid",80);
char messageFromS [80];
bzero (messageFromS, 80);
read (sd,messageFromS,80);
And I get something between the lines of
-ERR invalid command
But whenever I send a valid command, my client just freezes up after calling read and I have to force quit
write (sd,"user validuser",80);
char messageFromS [80];
bzero (messageFromS, 80);
read (sd,messageFromS,80);
Afterwards, I decided to use select() because I know it's a good practice, and maybe it could give good results
//function returns true (1) if we can read from the socket
bool isClosed(int sock)
{
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(sock, &rfd);
timeval tv;
//timeout value is set to 5 seconds
tv.tv_sec = 5;
select(sock+1, &rfd, 0, 0, &tv);
if (!FD_ISSET(sock, &rfd))
return false;
int n = 0;
ioctl(sock, FIONREAD, &n);
return n == 0;
}
But it seems that whenever I call
isClosed(sd)
It always returns True.
This is the point where I cannot think of any other options. Is there anything that Telnet has that my miniature client doesn't ?
EDIT: Thank you for your answers.
I played around with reading all the messages received byte by byte, until it found a termination character (apparently it wasn't NULL), and, after re-reading the RFC for pop3 (https://www.rfc-editor.org/rfc/rfc1081) closely I realized that I wasn't ending my commands properly. I should have appended '\r' and '\n' to the end of all commands sent.
I also checked the select () command, which returned -1 and set the tv.tv_usec = 0 which pretty much solved it.
Thank you for your answers.
I played around with reading all the messages received byte by byte, until it found a termination character (apparently it wasn't NULL), and, after re-reading the RFC for pop3 (https://www.rfc-editor.org/rfc/rfc1081) closely I realized that I wasn't ending my commands properly. I should have appended '\r' and '\n' to the end of all commands sent.
I also checked the select () command, which returned -1 and set the tv.tv_usec = 0 which pretty much solved it.
– Shoshinsha purogurama
I am making a web proxy using sockets in C. Basically, I listen to a given port number, take in an HTML request from it, make the request, and then send what I get back where it came from.
I've got the first part working. I'm able to read in the request and send it to the necessary web server, and I get a valid response. I'm just not sure how to send that response to the port where it was asked for.
(I'm testing my code using Netcat to make the request and get a response back, and at the moment the response I am trying to send is not being printed by Netcat.)
Here's my relevant code:
struct sockaddr_in port;
bzero((char *) &port, sizeof(port));
port.sin_family = AF_INET;
port.sin_port = htons(atoi(argv[1]));
port.sin_addr.s_addr = INADDR_ANY;
int socket;
int acceptSocket;
char response[RESPONSE_SIZE];
socket = Socket(AF_INET, SOCK_STREAM, 0);
Bind(socket, (struct sockaddr *) &port, sizeof(port));
Listen(socket, 0);
acceptSocket = Accept(socket, NULL, NULL);
if (acceptSocket >= 0)
printf("Connection open on port %s\n", argv[1]);
if (!ForwardHTTPRequest(acceptSocket, response))
printf("Forward error\n");
shutdown(socket, 0);
Connect(socket, (struct sockaddr *) &port, sizeof(port));
Send(socket, response, strlen(response), 0);
The last three lines are my attempt to send the response back. I shut down the read side of the socket, connect in order to send, and then send. This isn't producing any response though.
acceptSocket is the socket you're using for communications one the session is established. Just send a message back on that socket before you shut it down.
It's unusual to shut down the controlling socket unless you're absolutely sure you don't want to serve any more requests. The basic workflow of a server is:
create listensocket
bind listensocket
while working:
worksocket = accept listensocket
read and write to worksocket as much as you want
close worksocket
shutdown/close listensocket
(although, for responsiveness, the actual work done on worksocket is farmed off to a different thread or process, so that the server can handle subsequent requests without waiting).