Avatar billede nomak Nybegynder
19. marts 2003 - 21:42 Der er 7 kommentarer og
1 løsning

C server i unix

Hey Eksperter!

Jeg er forholdsvis ny i C sockets på en UNIX maskine, så jeg mangler lidt hjælp!

Det jeg mangler er en chat-server som kan flg:

*Mulighed for flere brugere på samme tid

*hver bruger får tildelt en connection id (noget ala cid5) så man kan skrive privat mellem brugerne

*mulighed for at skrive til alle brugere..

Har selv lave en server som kan have EN bruger på, men har meget besvær med at lave så flere brugere kan være på..

clienten skal bare være telnet.. laver selv en anden client senere..

Tilbyder 150 points og evt. web-hosting med PHP, MySQL og ubegrænset plads..

mail: nomak@diggy.dk
msn: niels_jensen@msn.com
icq: 129350634

/NoMak
Avatar billede morw Nybegynder
19. marts 2003 - 21:49 #1
Lytter lige med... Har en socket chat i PHP, hvis du kan bruge den?
Avatar billede nomak Nybegynder
19. marts 2003 - 21:50 #2
morw -> vil gerne kigge lidt på den hvis det er.. men tvivler på det ikke sluger for meget båndbredde og kraft fra maskinen
Avatar billede morw Nybegynder
19. marts 2003 - 21:50 #3
Kan være du kan skrive den om til c:

#!/usr/local/bin/php
<?
/* a simple 'partyline' example of how to use socket_select() and co. to create
* a multi-socket php listening daemon with multi-client support.
*
* modify at will. (by dave on irc.dal.net)
*/

$listen_addr = '0.0.0.0';
$listen_port = 10000;

define('STATE_NICKNAME', 1);
define('STATE_CHATTING', 2);

/* this is to be a daemon, don't want to auto-timeout and no error messages! */
set_time_limit(0);
error_reporting(0);

/* display error message */
function myerror() {
  echo '[error]: ' . socket_strerror(socket_last_error()) . "\n";
}

/* display error message and die */
function myerror_d() {
  myerror();
  die();
}

/* send a message to a socket */
function send_single($sock, $message) {
  socket_write($sock, "$message\n");
}

/* send a message to all client sockets */
function send_all($message, $state = STATE_CHATTING) {
  global $s_clients, $cdata;

  foreach ($s_clients as $sock)
    if ($cdata[$sock]['state'] == $state || $state == 0)
      send_single($sock, $message);

}

/* send a message to all client sockets except one */
function send_all_butone($sock, $message, $state = STATE_CHATTING) {
  global $s_clients, $cdata;

  foreach ($s_clients as $mysock)
    if ($mysock != $sock && $cdata[$mysock]['state'] == $state || $state == 0)
      send_single($mysock, $message);

}

/* handle incoming data */
function handle_data($sock, $read) {
  global $cdata;

  if ($cdata[$sock]['buf'] != '')
    $read = $cdata[$sock]['buf'] . $read;

  $read = str_replace("\r", '', $read);

  $cdata[$sock]['buf'] = substr(strrchr($read, "\n"), 1);
  $read = substr($read, 0, strpos($read, "\n"));

  if ($cdata[$sock]['state'] == STATE_NICKNAME)
    handle_nickname($sock, $read);
  else
    handle_chat($sock, $read);
}

/* handle nickname entry */
function handle_nickname($sock, $nick) {
  global $s_clients, $cdata;

  if (!preg_match('/^[a-zA-Z]{1,10}$/', $nick)) {
    send_single($sock, "That nick is invalid. Please choose another:");
    return;
  }

  foreach ($s_clients as $mysock)
    if (strcasecmp($cdata[$mysock]['nick'], $nick) == 0) {
      send_single($sock, "That nick is already in use. Please choose another:");
      return;
    }

  $cdata[$sock]['nick'] = $nick;
  $cdata[$sock]['state'] = STATE_CHATTING;
  on_join($sock);
}

/* handle chat text */
function handle_chat($sock, $data) {
  global $cdata;

  /* do who command */
  if ($data == '.who') {
    do_who($sock);
    return;
  }
  else if ($data[0] == '.') {
    send_single($sock, "Invalid command.");
    return;
  }

  $nick = $cdata[$sock]['nick'];
  send_all_butone($sock, "<$nick> $data");
}

/* client has joined */
function on_join($sock) {
  global $cdata;

  $nick = $cdata[$sock]['nick'];
  $addr = $cdata[$sock]['addr'];
  send_all("*** Joins: $nick ($addr)");
}

/* client has quit */
function on_quit($sock) {
  global $cdata;

  $nick = $cdata[$sock]['nick'];
  $addr = $cdata[$sock]['addr'];
  send_all_butone($sock, "*** Quits: $nick ($addr)");
}

/* who command */
function do_who($sock) {
  global $s_clients, $cdata;

  foreach ($s_clients as $mysock) {
    $state = $cdata[$mysock]['state'];

    if ($state == STATE_NICKNAME)
      send_single($sock, sprintf('[nickname] (%s)', $cdata[$mysock]['addr']));
    else
      send_single($sock, sprintf('[chatting] %10s (%s)', $cdata[$mysock]['nick'], $cdata[$mysock]['addr']));
  }
}     

/* assign listening socket */
if (!($s_listen = socket_create(AF_INET, SOCK_STREAM, 0)))
  myerror_d();

/* reuse listening socket address */
if (!socket_set_option($s_listen, SOL_SOCKET, SO_REUSEADDR, 1))
  myerror_d();

/* set socket to non-blocking */
if (!socket_set_nonblock($s_listen))
  myerror_d();

/* bind listening socket to specific address/port */
if (!socket_bind($s_listen, $listen_addr, $listen_port))
  myerror_d();

/* listen on listening socket */
if (!socket_listen($s_listen))
  myerror_d();

/* set initial vars and loop until $abort is set to true */
$s_clients = Array();
$abort = false;

while (!$abort) {
  /* sockets we want to pay attention to */
  $set = array_merge($s_listen, $s_clients);

  if (socket_select($set, $set_w = NULL, $set_e = NULL, 1, 0) > 0) {
    /* loop through sockets */
    foreach ($set as $sock) {
      /* listening socket has a connection, deal with it */
      if ($sock == $s_listen) {
        if (!($this = socket_accept($s_listen)))
          myerror();
        else {
          /* add socket to client list and announce connection */
          $s_clients[$this] = $this;
          socket_getpeername($this, $addr);
          $cdata[$this]['addr']  = $addr;
          $cdata[$this]['buf']  = '';
          $cdata[$this]['state'] = STATE_NICKNAME;

          echo "[connection]: $addr\n";
          send_single($this, 'Enter a nickname:');
        }
      }
      else {
        /* client socket has incoming data */
        if (($read = socket_read($sock, 1024)) === false || $read == '') {
          if ($read != '')
            myerror();
          else /* no error, but connection was closed, so tell everyone */
            on_quit($sock);

          /* remove client from arrays */
          unset($s_clients[$sock]);
          unset($cdata[$sock]);
        }
        else {
          /* only want data with a newline */
          if (strchr($read, "\n") === false)
            $cdata[$sock]['buf'] .= $read;
          else
            handle_data($sock, $read);
        }
      }
    }
  }
}

echo "[end]\n";

?>
Avatar billede segmose Nybegynder
20. marts 2003 - 08:56 #4
Måske kan du bruge dette? det kræver nok lidt arbejde fra din side.

http://www.ecst.csuchico.edu/~beej/guide/net/html/advanced.html#select

se efter selectserver.c
Avatar billede nomak Nybegynder
20. marts 2003 - 14:16 #5
Det ser ud til at være noget af det rigtige.. bortset fra en ting; hver bruger skulle gerne have en connection id så de kan skrive privat sammen..
Avatar billede segmose Nybegynder
20. marts 2003 - 15:18 #6
// we got some data from a client
for(j = 0; j <= fdmax; j++) {
  // send to everyone!
  if (FD_ISSET(j, &master)) {
    // except the listener and ourselves
// Analyser buf, fx. "5: noget tekst"
// 5 er så fd 5 så skriv kun til fd 5.
// husk at fortælle brugeren hvad han selv hedder
// også skriv foran alle beskeder hvem det kommer fra.
    if (j != listener && j != i) {
      if (send(j, buf, nbytes, 0) == -1) {
        perror("send");
      }
    }
  }
}
Avatar billede nomak Nybegynder
20. marts 2003 - 16:26 #7
OK, den fattede jeg så ikke...

tænkte på en funktion ala:

int send_to_fd(int fd, char *buf) {
if (send(fd, buf, nbytes, 0) == -1) {
perror("send");
}
}
Avatar billede segmose Nybegynder
21. marts 2003 - 08:51 #8
Du skal efter nedenstående kommentar, check om det kun skal sendes til en modtager eller til alle, nemest ville være at antage at send til alle er default og man skal skrive fd-nummer + ':' istarten for at skrive til et bestemt fd-nummer.

// we got some data from a client
// pseudo code
if (to one client)
  send_to_fd(fd, buf)
else
  send to all
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester