SoFunction
Updated on 2025-04-09

Using sockets in php: Get articles from newsgroups

PHP can open Socket ports on remote or local hosts. This article is a small example of using Socket: Connect to a Usenet newsgroup server, talk to the server, and download some articles from the newsgroup.


Open a socket in php
Use fsocckopen() to open a socket. This function can be used in both php3 and php4. The function declaration is like this:


int fsockopen (string hostname, int port _
[, int errno [, string errstr [, double timeout]]])

 
This function will open a TCP connection to the port port of the hostname. The hostname can be a valid domain name or an IP address. For udp connections, you must specify the protocol: udp://hostname. For unix domains, the hostname uses the path to the socket, in which case the port port must be set to 0. The optional timeout parameter is used to set the time to wait for a socket to be opened in seconds.


For more information about fsocopen(), please refer to: /manual/


Internet News Transmission Protocol
Access to the news group server needs to be done through a protocol called NNTP (Network News Transfer Protocol). This protocol has detailed details in rfc977, which can be obtained at http:///Protocols/rfc977/. This document describes how to connect to an NNTP server, how to talk to the server, and different commands to complete these tasks.


connect
To connect to an NNTP server, you need to know its host name (or IP address) and the port it listens on. To avoid a connection attempt failing, causing the program to hang, you should use the timeout parameter.
    <?php
      $cfgServer   = "";
      $cfgPort     = 119;
      $cfgTimeOut  = 10;

      //open a socket
      if(!$cfgTimeOut)
         // without timeout
         $usenet_handle = fsockopen($cfgServer, $cfgPort);
      else
         // with timeout
         $usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);

      if(!$usenet_handle) {
          echo "Connection failed.\n";
          exit();
      }
      else {
          echo "Connected.\n";
          $tmp = fgets($usenet_handle, 1024);
      }

?>
Talk to the server

Now that we have connected to the server, we can talk to the server through the socket we opened earlier. For example, we need to get the latest 10 articles from a certain news group. RFC977 points out that the first step is to use the GROUP command to select the correct news group:
GROUP ggg
The parameter ggg is the name of the newsgroup to be selected (for example, ""), which is required. A list of available newsgroups can be obtained using the LIST command. After the command to select the news group is successful, return the article number of the first and last articles in the group, and the number of articles in the group.
   

Here is an example:
    chrome:~$ telnet 119
    Trying ...
    Connected to .
    Escape character is '^]'.
    200 InterNetNews NNRP server INN 2.2.2 13-Dec-1999 ready (posting ok).
    GROUP
    211 232 222996 223235
    quit
    205 .

After receiving the command GROUP, the server returns "211 232 222996 223235". 211 is the return code defined in RFC, indicating that the command has been successfully executed. The return information also pointed out that there are now 232 articles, the earliest article number is 222996, and the latest article number is 223235. We see that 222996+232 does not equal 223235. The 7 lost articles were deleted from the server for some reason, maybe because they were canceled by its legal author (which is possible and easy to do), or because they were deleted because they were flooded articles.
   

Things to note that some servers may require authentication before selecting a newsgroup, depending on whether this is a public or private server. It is also possible that the server allows anyone to read the article, but posting requires authentication.

    <?php

      //$cfgUser    = "xxxxxx";
      //$cfgPasswd  = "yyyyyy";
      $cfgNewsGroup = "";

      //identification required on private server
      if($cfgUser) {
          fputs($usenet_handle, "AUTHINFO USER ".$cfgUser."n");
          $tmp = fgets($usenet_handle, 1024);
          fputs($usenet_handle, "AUTHINFO PASS ".$cfgPasswd."n");
          $tmp = fgets($usenet_handle, 1024);

          //check error

          if($tmp != "281 Okrn") {
              echo "502 Authentication errorn";
              exit();
          }
  }

  //select newsgroup

  fput($usenet_handle, "GROUP ".$cfgNewsGroup."n");
  $tmp = fgets($usenet_handle, 1024);

  if($tmp == "480 Authentication required for commandrn") {
     echo $tmp;
     exit();
  }

  $info = split(" ", $tmp);
  $first= $info[2];
  $last = $info[3];

  printf("First : %sn", $first);
  printf("Last : %lastn", $last);

?>