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
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";
?>
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");
}
}
}
}
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");
}
}