read / write on socket descriptors linux c - sockets

I am trying to send the contents of a file from the server to the client , I am reading the file line by line using fgets and writing to the socket descriptor line by line , on the client side , i am in an a while loop , reading the sent contents.I am not being able to terminate the server sending sequence , i.e the client keeps reading the buffer and the next program line is not executed , I think thers something wrong with my way of sending or recieving . here is the code :
server :
filefd = fopen("clients.txt","a+");
while(fgets(filcont,300,filefd) != NULL)
{// write whole file contents to client
n=write(newsockfd,filcont,strlen(filcont));
if(n==0) break;
memset(filcont,'\0',300);
}
fclose(filefd);
client side :
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
printf("%s\nbytes read :%d \n",buffer,n);
memset(buffer,'\0',256);
}
printf("Enter peer name ( except yours ) to send connection request : \n");
the above line ( printf , peer name doesnot get executed until i terminate the server)

I was able to figure it out , I sent the file contents from the server using fread instead of fgets ( line by line ) and used a single read() at the client . this was the quick fix.
But I also figured out another technique when in case you have to compulsorily use fgets , where the while loop at the client side makes the socket nonblocking for read and then blocking again , the code is pasted below.
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
if(n==-1) printf("\nNon blocking read failed congrats");
printf("%s\n",buffer);
memset(buffer,'\0',256);
}
printf("\nbytes read :%d \n",n);
val = fcntl(sockfd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags; // makes it blocking again
fcntl(sockfd,F_SETFL,val);
The code from stackoverflow was refered to make the socket blocking

Related

python socket trying to set a specific time the recv() function would work for [duplicate]

I need to set timeout on python's socket recv method. How to do it?
The typical approach is to use select() to wait until data is available or until the timeout occurs. Only call recv() when data is actually available. To be safe, we also set the socket to non-blocking mode to guarantee that recv() will never block indefinitely. select() can also be used to wait on more than one socket at a time.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
If you have a lot of open file descriptors, poll() is a more efficient alternative to select().
Another option is to set a timeout for all operations on the socket using socket.settimeout(), but I see that you've explicitly rejected that solution in another answer.
there's socket.settimeout()
As mentioned both select.select() and socket.settimeout() will work.
Note you might need to call settimeout twice for your needs, e.g.
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()
# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)
You could set timeout before receiving the response and after having received the response set it back to None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
The timeout that you are looking for is the connection socket's timeout not the primary socket's, if you implement the server side. In other words, there is another timeout for the connection socket object, which is the output of socket.accept() method. Therefore:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5) # This is the one that affects recv() method.
connection.gettimeout() # This should result 5
sock.gettimeout() # This outputs None when not set previously, if I remember correctly.
If you implement the client side, it would be simple.
sock.connect(server_address)
sock.settimeout(3)
Got a bit confused from the top answers so I've wrote a small gist with examples for better understanding.
Option #1 - socket.settimeout()
Will raise an exception in case the sock.recv() waits for more than the defined timeout.
import socket
sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.settimeout(timeout_seconds)
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = sock.recv(4096)
data = sock.recv(4096) # <- will raise a socket.timeout exception here
Option #2 - select.select()
Waits until data is sent until the timeout is reached. I've tweaked Daniel's answer so it will raise an exception
import select
import socket
def recv_timeout(sock, bytes_to_read, timeout_seconds):
sock.setblocking(0)
ready = select.select([sock], [], [], timeout_seconds)
if ready[0]:
return sock.recv(bytes_to_read)
raise socket.timeout()
sock = socket.create_connection(('neverssl.com', 80))
timeout_seconds = 2
sock.send(b'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n')
data = recv_timeout(sock, 4096, timeout_seconds)
data = recv_timeout(sock, 4096, timeout_seconds) # <- will raise a socket.timeout exception here
You can use socket.settimeout() which accepts a integer argument representing number of seconds. For example, socket.settimeout(1) will set the timeout to 1 second
try this it uses the underlying C.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
As mentioned in previous replies, you can use something like: .settimeout()
For example:
import socket
s = socket.socket()
s.settimeout(1) # Sets the socket to timeout after 1 second of no activity
host, port = "somehost", 4444
s.connect((host, port))
s.send("Hello World!\r\n")
try:
rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
print("Didn't receive data! [Timeout]")
finally:
s.close()
I hope this helps!!
#! /usr/bin/python3.6
# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801
s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
try:
data, address = s.recvfrom(BUFFER_SIZE)
except socket.timeout:
print("Didn't receive data! [Timeout 5s]")
continue
Shout out to: https://boltons.readthedocs.io/en/latest/socketutils.html
It provides a buffered socket, this provides a lot of very useful functionality such as:
.recv_until() #recv until occurrence of bytes
.recv_closed() #recv until close
.peek() #peek at buffer but don't pop values
.settimeout() #configure timeout (including recv timeout)

ESP8266: How to send TCP messages using AT+CIPSEND command

I am experimenting with Arduino and ESP8266 module, and now I am trying to send some sensor data to a TCP server. For this purposes I am using AT+CIPSTART command (to establish a TCP connection) and AT+CIPSEND to send the data.
If I am testing it using Serial Monitor, it works fine. After entering CIPSEND command I can write some text in a terminal and this message/text will be sent to the TCP server.
When I am trying to make it inside Arduino sketch, then it sends an empty message. The connection works, but I do not see any data.
How can I send a message text (msg) with my TCP packet?
Here is a code snippet
// ESP8266 Client
String cmd = "AT+CIPSTART=\"TCP\",\"";// Setup TCP connection
cmd += IP;
cmd += "\",3103";
sendDebug(cmd);
delay(2000);
if( Serial.find( "Error" ) )
{
debug.print( "RECEIVED: Error\nExit1" );
return;
}
String msg = "test";
Serial.print( "AT+CIPSEND=" );
Serial.println( msg.length() );
if(Serial.find( ">" ) )
{
debug.print(">");
debug.print(msg);
Serial.print(msg);
}
else
{
sendDebug( "AT+CIPCLOSE" );//close TCP connection
}
if( Serial.find("OK") )
{
debug.println( "RECEIVED: OK" );
}
else
{
debug.println( "RECEIVED: Error\nExit2" );
}
}
First of all, Select how much character or byte is needed to transmit. It is better to use softwareSerial library to connect with ESP8266 and send AT commands.
Suppose yow want to send 5 bytes.Type the following AT commands and must give a delay more than 100 millisecond before sending data. Here "\r" is carriage return and "\n" is new line. After including this, ESP8266 can understand you have ended the command.
esp.print("AT+CIPSEND=5\r\n");
delay(1000);
esp.print("Hello");
Your code is not working because you are using unvarnished transmission mode. So to complete a packet you need to transmit 2048 bytes which you are not writing.

An error in my code to be a simple ftp

I met an error when running codes at the bottom. It's like a simple ftp.
I use python2.6.6 and CentOS release 6.8
In most linux server, it gets right results like this:(I'm very sorry that I have just sign up and couldn't )
Clinet:
[root#Test ftp]# python client.py
path:put|/home/aaa.txt
Server:
[root#Test ftp]# python server.py
connected...
pre_data:put|aaa.txt|4
cmd: put
file_name: aaa.txt
file_size: 4
upload successed.
But I get errors in some server(such as my own VM in my PC). I have done lots of tests(python2.6/python2.7, Centos6.5/Centos6.7) and found this error is not because them. Here is the error imformation:
[root#Lewis-VM ftp]# python server.py
connected...
pre_data:put|aaa.txt|7sdfsdf ###Here gets the wrong result, "sdfsdf" is the content of /home/aaa.txt and it shouldn't be sent here to 'file_size' and so it cause the "ValueError" below
cmd: put
file_name: aaa.txt
file_size: 7sdfsdf
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 10699)
Traceback (most recent call last):
File "/usr/lib64/python2.6/SocketServer.py", line 570, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib64/python2.6/SocketServer.py", line 332, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib64/python2.6/SocketServer.py", line 627, in __init__
self.handle()
File "server.py", line 30, in handle
if int(file_size)>recv_size:
ValueError: invalid literal for int() with base 10: '7sdfsdf\n'
What's more, I found that if I insert a time.sleep(1) between sk.send(cmd+"|"+file_name+'|'+str(file_size)) and sk.send(data) in client.py, the error will disappear. I have said that I did tests in different system and python versions and the error is not because them. So I guess that is it because of some system configs? I have check about socket.send() and socket.recv() in python.org but fount nothing helpful. So could somebody help me to explain why this happend?
The code are here:
#!/usr/bin/env python
#coding:utf-8
################
#This is server#
################
import SocketServer
import os
class MyServer(SocketServer.BaseRequestHandler):
def handle(self):
base_path = '/home/ftp/file'
conn = self.request
print 'connected...'
while True:
#####receive pre_data: we should get data like 'put|/home/aaa|7'
pre_data = conn.recv(1024)
print 'pre_data:' + pre_data
cmd,file_name,file_size = pre_data.split('|')
print 'cmd: ' + cmd
print 'file_name: '+ file_name
print 'file_size: '+ file_size
recv_size = 0
file_dir = os.path.join(base_path,file_name)
f = file(file_dir,'wb')
Flag = True
####receive 1024bytes each time
while Flag:
if int(file_size)>recv_size:
data = conn.recv(1024)
recv_size+=len(data)
else:
recv_size = 0
Flag = False
continue
f.write(data)
print 'upload successed.'
f.close()
instance = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()
#!/usr/bin/env python
#coding:utf-8
################
#This is client#
################
import socket
import sys
import os
ip_port = ('127.0.0.1',9999)
sk = socket.socket()
sk.connect(ip_port)
while True:
input = raw_input('path:')
#####we should input like 'put|/home/aaa.txt'
cmd,path = input.split('|')
file_name = os.path.basename(path)
file_size=os.stat(path).st_size
sk.send(cmd+"|"+file_name+'|'+str(file_size))
send_size = 0
f= file(path,'rb')
Flag = True
#####read 1024 bytes and send it to server each time
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
sk.send(data)
f.close()
sk.close()
The TCP is a stream of data. That is the problem. TCP do not need to keep message boundaries. So when a client calls something like
connection.send("0123456789")
connection.send("ABCDEFGHIJ")
then a naive server like
while True;
data = conn.recv(1024)
print data + "_"
may print any of:
0123456789_ABCDEFGHIJ_
0123456789ABCDEFGHIJ_
0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F_G_H_I_J_
The server has no chance to recognize how many sends client called because the TCP stack at client side just inserted data to a stream and the server must be able to process the data received in different number of buffers than the client used.
Your server must contain a logic to separate the header and the data. All of application protocols based on TCP use a mechanism to identify application level boundaries. For example HTTP separates headers and body by an empty line and it informs about the body length in a separate header.
Your program works correctly when server receives a header with the command, name and size in a separate buffer it it fails when client is fast enough and push the data into stream quickly and the server reads header and data in one chunk.

WSAECONNABORTED (10053) error received while calling send command after fixed iterations

I'm also facing some issue where a server sends data to client and client sends back the acknowledgement. But after certain iterations the socket is aborted and I'm getting WSAECONNABORTED (10053) while sending the acknowledgement back to server.
I'm on win7 64-bit machine.
Server code(this is perl code):
sub Send_Msg_to_SourceSelector
{
(my $msg)=#_;
my $msg_len = length("$msg")+1;
print "the message length is: $msg_len\n\n";
PrintLogFile(1, ">> $CurrentTime >> The message length is : $msg_len <<<<\n\n");
print "the SOCK1 is: SOCK\n\n";
PrintLogFile(1, ">> $CurrentTime >> The sent message is : $msg <<<<\n\n");
send $SOCK,$msg,$msg_len;
print "the SOCK2 is: $SOCK\n\n";
recv $SOCK,my $awk,3,0;
PrintLogFile(1, ">> $CurrentTime >> The acknowledgement received is : $awk <<<<\n\n");
print "the SOCK3 is: $SOCK\n\n";
}
Client code (this is in C...executable generated in visual studio 2013):
void RecvDataFromSequencer(SOCKET sock, FILE *Log)
{
char n,buffer[2000];
while(!FlagTestExecutionCompleted)
{
memset (buffer , 0 , 2000);
printf("The address of buffer before is: %d\n", buffer);
n = recv(sock,buffer,2000,0); //blocking call
printf("The address of buffer after is: %d\n", buffer);
printf("in recv func: %x\n", Log);
//printlogfile(Log, buffer);
fprintf(Log,"%s%s",buffer,"\n");
fprintf(Log,"%d%s",n,"\n");
fprintf(Log,"%s%d%s","FlagTestExecutionCompleted is ==> ",FlagTestExecutionCompleted,"\n");
fflush(Log);
if (n == -1)
{
printf("recv failed: %d\n", WSAGetLastError());
fprintf(Log,"%s%s",WSAGetLastError(),"\n");
error("ERROR reading from STATS");
fprintf(Log,"%s%s","ERROR reading from STATS","\n");
fflush(Log);
}
else
{
printf("\nMessage from STATS: %s\n",buffer);
strcpy(line_tcfile,buffer);
if(strstr(line_tcfile,"SessionCompleted"))
{
printf("\n End of Test Session");
FlagTestExecutionCompleted=1;
}
FlagNewTestCaseRecieved = 1;
}
//Send acknowledgement
Sleep(1000);
**n = send(sock,"ACK",3,0);
if (n == -1)
{
fprintf(Log,"%s%d%s","in send command FlagTestExecutionCompleted is ==> ",FlagTestExecutionCompleted,"\n");
printf("send failed: %d\n", WSAGetLastError());
fprintf(Log,"%s%s",WSAGetLastError(),"\n");**
fprintf(Log,"%s%s","ERROR writing to STATS","\n");
fprintf(Log,"%d%s",n,"\n");
fflush(Log);
error("ERROR writing to STATS");
}
In this the following is happening:
1. server reads a line and sends to client
2. client reads the line and sends back the acknowledgement back to server
3. this process happens successfully to some tests
4. after some time the while sending back acknowledgement to server through send command, it returns WSAECONNABORTED (10053)
I don't know what is the reason.
Please help
Thanks,
Pankaj

asynchronous client socket closing?

hey i want to ask a question about asynchronous socket communication on c#. everything is working well for now apart from closing clients. server doesnot close immediately the worker socket for client when a client close its conneciton. it closes a few time later. how can i resolve this problem??
check this link http://msdn.microsoft.com/en-us/library/fx6588te.aspx#2 my problem is that I can't keep the connection open after I receive a message from the client.
If I do as said on that sample the connection is closed immediately after receiving the message.
If I don't close the connection I can only receive one message and nothing more.
If you have any solution to this throw it this way.
I got it!
If anybody else has this problem they should do the following.
Change this code:
content = state.sb.ToString()
to this:
content = state.sb.ToString().TrimEnd(New Char() {ChrW(13)})
then you should change this:
If content.IndexOf("<EOF>") > -1 Then
to this:
If content.IndexOf(New Char() {ChrW(13)}) > -1 Then
this will receive Enter (chrw(13)) as the end of line.
then here:
Console.WriteLine("Read {0} bytes from socket. " + vbLf + " Data : {1}", content.Length, content)
' Echo the data back to the client.
Send(handler, content)
you should do this:
Console.WriteLine("Read {0} bytes from socket. " + vbLf + " Data : {1}", content.Length, mid(content,1,content.length -2))
' Echo the data back to the client.
'Send(handler, content)
content = String.Empty
state.sb.Clear()
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
And your done.