socket_bind(): unable to bind address - php

I've seen this question asked at least a dozen times. None of the responses helped me.
The code:
$host = "127.0.0.1";
$port = 80;
//no timeout
set_time_limit(0);
//create socket
$socket=socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo socket_strerror(socket_last_error($socket));
exit;
}
$result = socket_bind($socket, $host, $port) or die("Could not bind socket\n");
The 'if' statement was added because one response suggested putting it in there. Didn't seem to do anything for me. I plan to take it out. Anyway, my error is:
Warning: socket_bind(): unable to bind address [10013]: An attempt was made to access a socket in a way forbidden by its access permissions.
And, yes, I get that its supposed to mean the port is in use by another process. I changed the port number about 30 times. I temporarily turned off my (Windows 8) firewall. I ran netstat and I see that these ports don't close so I have like 30 sockets with the same PID and name.
So, my question is: what am I doing wrong?

Thanks to those that responded, but I figured out the problem on my own. The tutorial I used said to navigate to the server.php file. Don't laugh, but I navigated there via the browser. So, that message was popping up on my browser.
I ran the same file in the command prompt and I was either getting that error or it looked like it was hanging there depending on the port I chose. It wasn't crashing... it just had nothing to output. I gave it something to output (yay echo statements!!).
Anyway, thanks again.

To bind to a port below 1024 the process needs privileged rights. Typical only root could do this.
For a more detailed discussion in this topic please read here: Is there a way for non-root processes to bind to "privileged" ports on Linux?

Most frequently the reason that you'll get this error is that the socket you're trying to use is already in use by another program. You're trying to open a socket to listen on port 80, what port is apache listening on? If it's also port 80, there's your problem.

Related

How to create a persistant php listening server

I have some embedded devices which connect to their sever (supplied software for windows) running on port 6000.
I'm confused as to how this works as my understanding is that when a tcp connection is made on a port, that's it, the port is occupied an no other connections can be made.
But I guess this logic is wrong as multiple devices can connect to their server software just as a web server can accept multiple connections on port 80.
When I run netcat on an ubuntu server with the command nc -l -k 6000 it seems to do what I want, I can see the messages coming in one after another from multiple devices.
From the netcat manual:
-k Forces nc to stay listening for another connection after its cur-
rent connection is completed. It is an error to use this option
without the -l option.
I tried to achieve a similar scenario with php but I failed. Here's what I have so far:
<?php
$address = "0.0.0.0";
$port = 6000;
$mysock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($mysock, $address, $port) or die('Could not bind to address');
socket_listen($mysock, 5);
$client = socket_accept($mysock);
while (true) {
$input = socket_read($client, 1);
echo $input;
}
?>
I can see the first message from the first device that connects but after that nothing. Also this seems to be the wrong approach as the while loop causes high cpu usage.
Note I'm running the php script at the command line on an ubuntu server.
I realize that this code will only accept one client, but how can I change it so that it will behave like nc and accept multiple connections. Sorry if the question seems vague, I really don't know where to begin. Any help is appreciated

how to use php sockets to write string

So Im trying to get my head wrapped around this....
I open the port
$remip = $_SERVER['SERVER_ADDR']; //Grab my server address
$fp = fsockopen($remip, 80, $errno, $errstr, 10);//Godaddy hosting only 80 and 443 ports work
//fsockopen(ip address , port, IDK, IDK, timeout delay)
so now the ports open or if not maybe some error checking to be sure
if (!$fp) { echo "$errstr ($errno)<br>\n"; exit; } //Not sure what this echos out but its clear how it stops errors
So now that the port is open any ip/client can connect on this port????
Ill assume I can now connect....
So on my client I open a socket to my server ip address port tcp connection.....
The php file includes something like
else {$out = "hello, 80\r\n"; //out specifies the string to be written , bytes to write
fwrite($fp, $out); //$fp is the handle
fclose($fp)}//close the connection
at this point ill assume that my client gets the hello written to it ..
finish up by closing the connection
Im entirely new to this so Im attempting to understand some sample code here...
So how long is this socket open for? If i want to keep this port open do i need to do a cron job to launch this file periodically.
Im 100% sure that I have got something wrong here so please set me straight.
I think you have a misconception of what fsockopen does. In your example your fsockopen does not actually open port 80 (as in opening a server socket), but it opens a client socket that connects to port 80 on the server itself. It actually does open a (client) port which gets a (not completely) random number.
After you connected using fsockopen you can send HTTP commands to the webserver such as GET /index.php
What you need to use is socket_listen() and socket_bind(). There are a few places in the docs that show you how to get PHP listening on a socket: http://www.php.net/manual/en/function.socket-listen.php
I suggest you read and try them out by simply testing then with a unix tool called netcat (nc <ip_address> <port> command normally)

socket_bind() unable to bind address

I'm trying to create a Web Socket Server for a small project I am working on.
I have set up the server (located at home) and have port forwarded 80 and 22. I read this tutorial: here
And whenever I ssh into my server to run "startDarmon.php" I get the following error:
PHP Warning: socket_bind(): unable to bind address [98]: Address already in use in
/var/www/server/socket.class.php on line 48
2013-02-23 14:15:38 System: Socket bound to localhost:8000.
2013-02-23 14:15:38 System: Start listening on Socket
This is what i think is preventing my client from connecting to the server. So in the startDarmon.php file I have:
$WebSocket = new socketWebSocket('MY_IP_NOT_LAN_IP',8000);
And inside my client file, I have:
var host = "ws://MY_IP_NOT_LAN:8000/server/startDaemon.php";
Does anyone have any suggestions to why this is not allowing me to establish a connection?
I'm guessing the issue is on the Linux server.
Run the netstat -a -p -n command under root (e.g. with sudo) to understand which process is using that port. Then perhaps do a setsockopt(2) with SO_REUSEADDR
(see socket(7) for more).
The TCP protocol has some specified delays in minutes (eg keepalive, etc etc...). See e.g. tcp(7)
I do suggest reading a good book on Linux system programming like Advanced Linux Programming and perhaps some material on network programming.
You can reuse an address using the setting below:
if ( ! socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1))
{
echo socket_strerror(socket_last_error($sock));
exit;
}
Another application is already using the port that you are trying to use.You can run
lsof -i:port_no
to make the port free.

socket_accept seems to hang on the first connection

I'm trying to make a simple listener on port 8195. When I try the following code block in PHP CLI conditions, it only shows 'Test' once, then hangs. If I delete the file 'votifier.run', the file designed to be the on/off switch, it still continues to hang. It never shows 'Client connected'.
Furthermore, if I try to connect to the host via Telnet on port 8195 while the script is running, I simply get a connection failed message. It's like it's looking for one connection and just not giving up.
// Set the IP and port to listen to
$address = 'localhost';
$port = 8195;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port);
// Start listening for connections
socket_listen($sock);
// Loop continuously
while ( file_exists('votifier.run') ) {
echo 'Test';
$client = socket_accept($sock);
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_timeout($client, 5);
// Send them our version
socket_write("VOTIFIER MCWEBLINK\n");
// Read the 256 byte block
$block = socket_read($client, 256);
...
The answer:
socket_accept() will usually hang until a connection is made. If a connection attempt was made, the script would continue, but because the socket was being created on localhost, it would only accept connections to it from localhost.
The fix is to use your external IP rather than 'localhost' or '127.0.0.1'. Then you can Telnet to it.
I'm just guessing here, but could it be that the address you are trying to bind to should not be a hostname?
If the socket is of the AF_INET family, the address is an IP in dotted-quad notation (e.g. 127.0.0.1).
EDIT
Ok, I've taken your script and tried to reproduce your error but couldn't. There are a couple of flaws in it but none that would cause a telnet client's connection attempt to fail.
Since none of the aforementioned applies, let's go thru the checklist one by one:
sockets module loaded/compiled
localhost does resolve to 127.0.0.1
the port isn't taken by any other application running
there's no rule of any sort of firewall that would prevent communication between the telnet client and your server
the machine which you connect from is allowed to connect to the server host (try the same host if it isn't)
the file that's being checked in the while-loop does exist
you are sure that there isn't another fatal error within your script that would prevent the snippet you posted from running
These are all the possible error sources I can think of, atm. Try fixing up the minor flaws first, then go thru the checklist.
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_option(
$client,
SOL_SOCKET,
SO_RCVTIMEO | SO_SNDTIMEO,
array('sec' => 5, 'usec' => 0)
);
// Send them our version
socket_write($client, "VOTIFIER MCWEBLINK\n");
^^^^^^^
// Read the 256 byte block
$block = socket_read($client, 256);
You should be using threads. If the client never sends anything your code will block in the read() method. Each accepted socket should be completely handled in a new thread.
You may want to check this:
PHP Votifier example for Minecraft Topsites
It explains how the code works, it's the basic function that makes the encryption, fills up the 256 blank spaces and sends the packet too. You can work a little with it as you may want to improve it.
You can see a live demo of the running php for the plugin here: http://topg.org/test_votifier

"Connection refused" error on socket_connect in php

I am trying to convert some code from perl to php.
Perl code looks like below:
my $handle = Connect($port, $host);
and I am trying to use socket to do the same thing in php.
I have tried socket_create and socket_connect,
socket_create and socket_bind, and fsocketopen.
As a result, I'm stuck with error messages saying "Connection refused" or "permission denied":
socket_connect() [function.socket-connect]: unable to connect [111]: Connection refused in
I am not sure if this is the problem I need to solve, or the problem of permission because the code in perl works fine (I did not write that code).
my php code looks like below:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if(!$socket){
die('Error: socket_create()');
}
if(!socket_connect($socket,$host,$port)) {
die('Error: socket_connect()');
}
I'm not the one who manages the server, so I will need to ask someone else for the access if it is a permission issue. What should I ask for specifically?
Or should I use some other function to connect to the server? I am new to perl, so I am not sure if socket_connect is the equivalent function to use or not.
Thanks.
If your perl code is able to establish the connection, no additional permissions should be needed to do the same in php. Connection refused means the remote host doesn't let you in (you probably connect to wrong address/port). Permission denied is more surprising, a lot of people have this kind of problem while running httpd scripts with SELinux enabled. If you're one of them, refer to the SELinux manpage:
SELinux policy can be setup such that httpd scripts are not allowed to connect out to the network. This would prevent a hacker from breaking into you httpd server and attacking other machines. If you need scripts to be able to connect you can set the httpd_can_network_connect boolean on:
setsebool -P httpd_can_network_connect 1
I have a few concers to your examples though. Connect from your Perl snippet doesn't seem to be the standard socket connect; I don't know which module it belongs to, but are you sure there is no magic behind the call? As socket_connect takes address in dotted-quad notation (for IPv4), make sure you're not passing a hostname (you would need to make a DNS lookup first). At the very end check if it's really a TCP socket you need, not UDP.

Categories