I was wondering if anyone would know how to write a script for me that would accept TCP connections.
If it’s possible that when a client connection occurs, it sends a response showing the time of day and then closes the connection
This might help you:
# date_time_server.py
import socket
from datetime import datetime
ip = "0.0.0.0"
port = 8000
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind((ip, port))
server.listen()
send_html_response = True
print("Server started on addresss:", ip, "port:", port)
while True:
conn, addr = server.accept()
print("replying to", addr)
if send_html_response:
response = str('HTTP/1.1 200 OK\nContent-Type: text/html\n\n' + str(datetime.now())).encode()
else:
response = str(datetime.now()).encode()
conn.send(response)
conn.close()
just run it using python3.5 date_time_server.py and then test it using you local system's browser by connecting to 127.0.0.1:8000 and current date-time will be displayed in the browser.
Related
I'm trying to get the both the client request and IP address from http requests to my HTTP.jl server (based on the basic server example in the docs).
using HTTP
using Sockets
const APP = HTTP.Router()
# My request handler function can see the request's method
# and target but not the IP address it came from
HTTP.#register(APP,"GET","/",req::HTTP.Request -> begin
println("$(req.method) request to $(req.target)")
"Hello, world!"
end)
HTTP.serve(
APP,
Sockets.localhost,
8081;
# My tcpisvalid function can see the client's
# IP address but not the HTTP request
tcpisvalid=sock::Sockets.TCPSocket -> begin
host, port = Sockets.getpeername(sock)
println("Request from $host:$port")
true
end
)
My best guess would be that there's a way to parse the TCPSocket.buffer into an HTTP request but I can't find any methods to do it.
Can you suggest a way to get an HTTP.Request from a TCPSocket or a different way to approach this problem?
Thanks in advance!
The router (APP) is a (collection of) "request handler(s)" which can only access the HTTP.Request -- you can not get the stream from it. Instead you can define a "stream handler", which is passed the stream. From the stream you can get the client's IP adress using Sockets.getpeername (requires HTTP.jl version 0.9.7 when called on a HTTP.Stream as in the examples below).
using HTTP, Sockets
const APP = HTTP.Router()
function request_handler(req::HTTP.Request)
println("$(req.method) request to $(req.target)")
return "Hello, world!"
end
HTTP.#register APP "GET" "/" request_handler
function stream_handler(http::HTTP.Stream)
host, port = Sockets.getpeername(http)
println("Request from $host:$port")
return HTTP.handle(APP, http) # regular handling
end
# HTTP.serve with stream=true to specify that stream_handler is a function
# that expects a HTTP.Stream as input (and not a HTTP.Request)
HTTP.serve(stream_handler, Sockets.localhost, 8081; stream=true) # <-- Note stream=true
# or HTTP.listen
HTTP.listen(stream_handler, Sockets.localhost, 8081)
My client receives every message from the server just fine after connecting, but the server's output is always this:
Client #1 connected.
first packet error: timeout
Looping client #1
message error: timeout
Looping client #1
message error: timeout
Looping client #1
message error: timeout
...etc...
I've messed around with some values on each side. It usually does nothing, but sometimes when messing with the server's timeout values it makes it so the server just hangs forever on client:send() or client:receive(). I can never get it so that both of them can exchange messages with eachother. Why?
My goal is to have a client and server that spend minimal time (<2-3ms) every loop so that I can spend a lot of time doing other things (this was part of a bigger program but I isolated it for easier testing of the issue) on both the client or server. I can't afford to have long, blocking calls so I set the timeout really low.
Server source:
socket = require("socket");
server = assert(socket.bind("*", 534));
ip, port = server:getsockname();
server:settimeout(0.03);
nClients = 0;
clients = {};
print("Server started.");
while true do
local client, err = server:accept();
if (not err) then
nClients = nClients + 1;
print("Client #"..nClients.." connected.");
clients[nClients] = client;
clients[nClients]:settimeout(0.03);
clients[nClients]:send("test");
local msg, err = clients[nClients]:receive();
if (not err) then
print("we got it");
else
print("first packet error: "..err);
end
end
for i=1,nClients do
if (clients[i] ~= nil) then
print("Looping client #"..i);
local msg, err = clients[i]:receive();
if (not err) then
print("message received: "..msg);
else
print("message error: "..err);
end
clients[nClients]:send("another message");
end
end
socket.sleep(0.01);
end
Client source:
socket = require("socket");
tcp = assert(socket.tcp());
ip, port = "127.0.0.1", 534;
print("Client started.");
tcp:settimeout(0.03);
tcp:connect(ip, port);
while true do
local a, b, msg = tcp:receive();
if (msg and #msg > 1) then
print("message received: "..msg);
end
tcp:send("message");
socket.sleep(0.01);
end
I am using the new Akka IO and followed this tutorial(which is a simple server-client application). My server actor system code looks like this:
// create the sever system
ActorSystem tcpServerSystem = ActorSystem.create("tcp-server-system");
// create the tcp actor
final ActorRef tcpServer = Tcp.get(tcpServerSystem).manager();
// create the server actor;
ActorRef serverActor = tcpServerSystem.actorOf(new Props(ServerActor.class).withRouter(new RoundRobinRouter(5)), "server");
// tell the tcp server to use an actor for listen connection on;
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
options.add(TcpSO.reuseAddress(true));
tcpServer.tell(TcpMessage.bind(serverActor, new InetSocketAddress("127.0.0.1", 12345), 10, options),
serverActor);
The ServerActor class it's just a plain actor that on it's onReceive does the followings:
logger.info("Received: " + o);
if (o instanceof Tcp.Connected){
connectionActor = getSender();
connectionActor.tell(TcpMessage.register(getSelf()), getSelf());
ByteStringBuilder byteStringBuilder = new ByteStringBuilder();
byteStringBuilder.putBytes("Hello Worlds".getBytes());
connectionActor.tell(TcpMessage.write(byteStringBuilder.result()), getSelf());
}
I am trying to test the server actor using netcat and have this "strange" behaviour: only the first client that connect tot the server is receiving the message send from the server. The nexts clients could connect to the server but does not receive the message. Also in debug mode the server actor doesn't get the Tcp.Connected message(except for the first connected client), so a registration message could not be sent to the client, althought the next clients could connect.
this is a known issue in the 2.2-M1 milestone, where the problem was that the TcpListener didn't register AcceptInterest on the selector unless it reached the configured BatchAcceptLimit, leading to it not being notified of new accepts if there where only a few connections pending.
It has been fixed and will be part of the next milestone release.
I have a project that uses TCP sockets to communicate between a server and one client. As of now I have been doing this on one computer so I have just used local address of "127.0.0.1" for the address to bind and connect to on both sides and its worked fine. Now I have a second computer to act as a client, but I don't know how to change the addresses accordingly. They are connected through a network that is not connected to the Internet. Before the code looked like this -
Server -
struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results
//store the connecting address and size
struct sockaddr_storage their_addr;
socklen_t their_addr_size;
memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET; //local address
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address
//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
return false;
}
//make socket
fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (fd < 0) {
printf("\nserver socket failure %m", errno);
return false;
}
//allow reuse of port
int yes=1;
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*) &yes,sizeof(int)) == -1) {
perror("setsockopt");
return false;
}
//unlink and bind
unlink("127.0.0.1");
if(bind (fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nBind error %m", errno);
return false;
}
Client -
struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results
memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET; //local address
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address
//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
return false;
}
//make socket
fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (fd < 0) {
printf("\nserver socket failure %m", errno);
return false;
}
//connect
if(connect(fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nclient connection failure %m", errno);
return false;
}
I know it should be simple, but I can't figure out how to change the IPs to get them to work. I tried setting the server computer's IP address in the quotes in these lines -
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0)
and
unlink("127.0.0.1");
and then change the address in the client code to the client computer's IP address in this line -
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0)
Whenever I do that, it tells me connection refused. I have also tried doing the opposite way of putting the server's address in the client's line and client's address in the server's lines along with a few other attempts. At this point I feel like I am just guessing though. So can someone please help me understand how to change this from using the local address with one computer to connecting two computers? Any help is appreciated.
First, unlink("127.0.0.1"); is totally wrong here, don't do that.
Then, you have two computers connected by some network. Both should have IP addresses. Replace 127.0.0.1 with the server's IP address in both client and the server. The server does not to have to know client's address beforehand - it'll get that information from the accept(2) call. The client needs server's address to know where to connect. The server needs its own address for the bind(2) call.
The main problem is that your putting AI_PASSIVE in your client code. AI_PASSIVE is meant for servers only (that's what it signals).
Also on the server side you should first of all not call unlink. That's for AF_UNIX sockets only, not AF_INET. Secondly you don't need to put "127.0.0.1" in the getaddrinfo line on the server side. It's better to use NULL to bind to all available addresses.
If you change those things, I believe your code should work. However you're actually supposed to loop on the getaddrinfo result using the ai_next pointer and try to connect to each result, using the first that succeeds.
Connection Refused usually means your client received a RST to his SYN. This is most often caused by the lack of a listening socket on the server, on the port you're trying to connect to.
Run your server
On the CLI, type netstat -ant. Do you see an entry that's in LISTEN state on your port?
Something like:
tcp4 0 0 *.3689 *.* LISTEN
I bet you do not, and therefore have a problem with your server listening socket. I also bet the changes you made this this line:
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {
Weren't quite right. Try changing that IP to 0.0.0.0 on the server to tell it to to bind to any IP on the system. On the client, that line should have the IP address of the server. You should also remove the unlink() call in the server; unnecessary.
If you do have a listening socket, then there's probably a firewall or something in between your boxes that's blocking the SYN. Try typing service iptables stop on the CLI of both systems.
I am truing to integrate fusemail in asp.net 2.0. I am using HttpWebRequest for requesting the API pages. It has recently come to my notice that HttpWebRequest fails the first time and then continues and subsequent requests succeed.
say ( i know if i use goto it is a bad programming approach) if i use this code
retry:
try
{
Uri uri = new Uri("http://www.fusemail.com/api/request.html");
if (uri.Scheme == Uri.UriSchemeHttp)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.PreAuthenticate = true;
request.Method =
WebRequestMethods.Http.Post;
//request.ReadWriteTimeout = System.Threading.Timeout.Infinite;
//request.Timeout = System.Threading.Timeout.Infinite;
request.ContentLength = data.Length;
request.ContentType =
"application/x-www-form-urlencoded";
//request.UserAgent = Request.UserAgent;
request.UserAgent = "Mozilla/4.0";
request.KeepAlive = false;
request.ServicePoint.Expect100Continue = true;
//request.Accept = "Accept: text/html,application/xhtml+xml,application/xml";
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
//Response.Write(tmp);
if (!String.IsNullOrEmpty(tmp))
{
return tmp;
}
}
return String.Empty;
}
catch (WebException ex)
{
goto retry;
}
it works after failing once. i am writing to a text file in case of an error and after i failed request it works the second time. I am using ASP.Net 2.0 and the website is hosted on IIS 7 with Windows Server 2008 Standard. Also pinging the API address it fails the first time and then responds
C:\>ping 67.207.202.118
Pinging 67.207.202.118 with 32 bytes of data:
Reply from 192.168.0.253: **Destination host unreachable**.
Reply from 67.207.202.118: bytes=32 time=218ms TTL=49
Reply from 67.207.202.118: bytes=32 time=218ms TTL=49
Reply from 67.207.202.118: bytes=32 time=217ms TTL=49
Ping statistics for 67.207.202.118:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 217ms, Maximum = 218ms, Average = 217ms
The first time it fails in HttpWebRequest it fails with this error
System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 67.207.202.118:80
Is there an authentication issue the first time?. i read on some forums it first sends a 401 Unauthorized and then it can connect. I am unable to verify this using Fiddler.
Is there anything wrong with IIS configuration?
This is not a programming issue at all, I have faced a similar problem later and it was a network configuration problem due to ISA server / Firewall settings.
You have to contact your network administrator to check this issue.
I wish this helped you.
Yours,
Mohamed Kamal Elbeah
Senior .Net Developer
I recently came by this same issue. The solution in my case involved my testing environment, since I had multiple Ethernet adapters connected to my computer. While you may have a different IP for each of your Ethernet adapters, if they are all assigned to the same subnet this may cause a problem. The TCP connection is only attempted using one NIC at a time. So in my case, on the first try it would attempt the connection on one adapter that was not connected to my remote host, then on the second try it would connect using the second adapter which was connected. - Hope this helps someone.