linux下c语言多进程即时通讯 服务器端怎样转发数据, 求救!!!

时间:2021-09-12 16:43:11
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <mysql/mysql.h>
#define MAXBUF 1024
#define MYPORT 7838  //宏定义定义通信端口
#define CLIENTQ 10 //宏定义,定义服务程序可以连接的最大客户数量
#define MAXC 100
#define WELCOME "|----------Welcome to the chat room! ----------|" 
#define SORRY "当前连接用户已达最大,请稍后重试!"

void ltrim(char *str)
{
char *t;
t=str;
while(*str==' ')
str++;
while(*t++=*str++);
}

void rtrim(char *str)  
{  
    char *tmp = str+strlen(str)-1;      
    while (*tmp == ' ' || *tmp == '\n' || *tmp == '\t')   
    {  
        *tmp = '\0';  
        tmp--;  
    }
}

void trim(char *str)
{
ltrim(str);
rtrim(str);
}

void bspace(char *str, int n) {
    int i;
    for (i=0; i<n; i++) {
str[i] = ' ';
    }
}

void itoa(int i,char*string)
{
   int power,j;
   j=i;
   for(power=1;j>=10;j/=10)
     power*=10;
   for(;power>0;power/=10)
   {
     *string++='0'+i/power;
     i%=power;
   }
   *string='\0';
}

//得到当前系统时间
void get_cur_time(char * time_str)
{
   time_t timep;
   struct tm *p_curtime;
   char *time_tmp;
   time_tmp=(char *)malloc(2);
   memset(time_tmp,0,2);

   memset(time_str,0,20);
   time(&timep);
   p_curtime = localtime(&timep);
   strcat(time_str," (");
   itoa(p_curtime->tm_hour,time_tmp);
   strcat(time_str,time_tmp);
   strcat(time_str,":");
   itoa(p_curtime->tm_min,time_tmp);
   strcat(time_str,time_tmp);
   strcat(time_str,":");
   itoa(p_curtime->tm_sec,time_tmp);
   strcat(time_str,time_tmp);
   strcat(time_str,")");
   free(time_tmp);
}

//拼接数据 目标串 = 操作码+当前用户名+对话用户名+内容
void get_string(char *des, char *src1, char *src2, char *src3, char *src4) {
        int i=0;
        for (i=0; i<4; i++) {
                des[i] = src1[i];
        }
        for (i=0; src2[i] != '\0'; i++) {
                des[i+4] = src2[i];
        }
        for (i=0; src3[i] != '\0'; i++) {
                des[i+24] = src3[i];
        }
        for (i=0; src4[i] != '\0'; i++) {
                des[i+44] = src4[i];
        }
        des[MAXBUF-1] = '\0';
}

int cli_fd[MAXC];
struct sockaddr_in cli_addr[MAXC];
int db_fd[MAXC];
int main(int argc, char **argv)
{
    int sockfd;
    socklen_t len;
    struct sockaddr_in se_addr;
    int index=0;
    char buf[MAXBUF + 1];
    fd_set rfds;
    struct timeval tv;
    int retval, maxfd = -1;
    char opcode[5], username[20], passwd[20];
    char temp_buf[MAXBUF+1], msg[MAXBUF+1];
    char sql[1024];
    int j=0;

    /* DATABASE PARAMS*/
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    char *server = "localhost";
    char *user = "root";
    char *password = "admin"; 
    char *database = "oicq";
    conn = NULL;
    conn = mysql_init(NULL);
    /* Connect to database */
    if (!mysql_real_connect(conn, server,
        user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
    }
    if (conn != NULL)
mysql_query(conn, "set names utf8"); 

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    bzero(&se_addr, sizeof(se_addr));
    se_addr.sin_family = AF_INET;
    se_addr.sin_port = htons(MYPORT);
    se_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(se_addr.sin_zero),0);

    if (bind(sockfd, (struct sockaddr *)&se_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    for (index=0; index<MAXC; index++) {
cli_fd[index] = -1;
db_fd[index] = -1;
    }
    if (listen(sockfd, CLIENTQ) == -1) {
        perror("listen");
        exit(1);
    }
    len = sizeof(struct sockaddr);
    while (1) {
for (index=0; index<MAXC; index++) {
db_fd[index] = -1;
     }
//得到在线用户占用的套接字描述符
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT cli_id FROM isline order by cli_id");
    if (mysql_query(conn, sql)) {
          fprintf(stderr, "%s\n", mysql_error(conn));
              exit(1);
    }
res = mysql_store_result(conn); 

//有个表存用户名 和 文件句柄数组的索引 
    while ((row = mysql_fetch_row(res)) != NULL) {
int tmp_fd = 0;
       tmp_fd = atoi(row[0]);
//表示tmp_fd对应的句柄已用
db_fd[tmp_fd] = 1;
//printf("%d  ", tmp_fd);
}
//搜索到可用的句柄则跳出
for (j=0; j<MAXC; j++) {
if (db_fd[j] == -1) break;
}
if ((cli_fd[j] = accept(sockfd, (struct sockaddr *)&cli_addr[j], &len)) < 0) {
perror("accept");
exit(errno);
}
if (j >= MAXC-1) {
send(cli_fd[j], SORRY, strlen(SORRY), 0);
close(cli_fd[j]);
bzero(&cli_addr[j], sizeof(struct sockaddr_in));
}
        printf("\nserver: got connection from %s, port %d, socket %d\n",inet_ntoa(cli_addr[j].sin_addr),ntohs(cli_addr[j].sin_port), cli_fd[j]);
send(cli_fd[j],WELCOME,strlen(WELCOME),0);//发送问候信息
memset(sql, '\0', sizeof(sql));

10 个解决方案

#1



int ppid = fork();
if (ppid == 0) {
if (fork() == 0) {
while (1) {
int save_index = j;
// 把集合清空
FD_ZERO(&rfds);
// 把标准输入句柄0加入到集合中 
//FD_SET(0, &rfds);
maxfd = 0;
// 把当前连接句柄cli_fd[index]加入到集合中 
for (index=0; index<MAXC; index++) {
if (cli_fd[index]>=0) {
FD_SET(cli_fd[index], &rfds);
if (cli_fd[index] > maxfd) {
maxfd = cli_fd[index];
}
}
}
// 设置最大等待时间
tv.tv_sec = 1;
tv.tv_usec = 0;
// 开始等待
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
for (index=0; index<MAXC; index++) {
if (cli_fd[index]>=0) {
if (retval == -1) {
printf("将退出,select出错! %s", strerror(errno));
close(cli_fd[index]);
bzero(&cli_addr[index], sizeof(struct sockaddr_in));
cli_fd[index] = -1;
break;
} else if (retval == 0) {
// printf("没有任何消息到来,用户也没有按键,继续等待……\n");
continue;
} else {
if (FD_ISSET(cli_fd[index], &rfds)) {
// 当前连接的socket上有消息到来则接收对方发过来的消息并显示 
bzero(buf, MAXBUF + 1);
// 接收客户端的消息
len = recv(cli_fd[index], buf, MAXBUF, 0);
if (len > 0) {
//printf("接收消息成功:'%s',共%d个字节的数据\n",buf, len);
int i=0;
opcode[0] = buf[0];
opcode[1] = buf[1];
opcode[2] = buf[2];
opcode[3] = buf[3];
opcode[4] = '\0';
bspace(username, sizeof(username));
bspace(passwd, sizeof(passwd));
for (i=0; i<20; i++) {
username[i] = buf[i+4];
}
username[19] = '\0';
rtrim(username);
for (i=0; i<20; i++) {
passwd[i] = buf[i+24];
}
passwd[19] = '\0';
rtrim(passwd);
for (i=44; i<sizeof(buf); i++) {
temp_buf[i-44] = buf[i];
}
temp_buf[sizeof(buf)-45] = '\0';
strncpy(msg, temp_buf, strlen(temp_buf));
trim(msg);
printf("%d", index);
if (!strncmp(opcode, "0000", 4)) {
printf("注册user=%s,passwd=%s\n", username, passwd);
bzero(opcode, sizeof(opcode));
//此处需要校验用户是否存在,返回对应的opcode
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM user where name='");
strcat(sql, username);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
if (record_nums > 0) {
//已有
strncpy(opcode, "0002", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
//可用
//添加用户
char db_index[5];
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO user(name, passwd) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, passwd);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

//添加在线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO isline(name, cli_id) values('");
strcat(sql, username);
strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

strncpy(opcode, "0001", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
}
} else if (!strncmp(opcode, "0010", 4)) {
//printf("登录user=%s,passwd=%s\n", username, passwd);
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM isline where name='");
strcat(sql, username);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
strncpy(opcode, "0013", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
strcpy(sql, "SELECT * FROM user where name='");
strcat(sql, username);
strcat(sql, "' and passwd='");
strcat(sql, passwd);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
char db_index[5];
//添加在线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO isline(name, cli_id) values('");
strcat(sql, username);
strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

//登录成功
strncpy(opcode, "0011", 4);
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
//登录失败
strncpy(opcode, "0012", 4);
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, "", "", "");
}
}
} else if (!strncmp(opcode, "0100", 4)) {
//printf("公聊user=%s,msg=%s\n", username, temp_buf);
bzero(opcode, sizeof(opcode));
strcpy(opcode, "0101");
//聊天记录,插入数据库
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO record(ufrom, msg, msg_id) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, msg);
strcat(sql, "', 2)");
//printf("%s", sql);
mysql_query(conn, sql);

bspace(buf, MAXBUF + 1);
get_string(buf, opcode, username, "", msg);
} else if (!strncmp(opcode, "0110", 4)) {
//get cli_fd[index] 向对应的用户发送信息
//printf("私信user=%s,msg=%s\n", username, temp_buf);
bzero(opcode, sizeof(opcode));

memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM isline where name='");
strcat(sql, passwd);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
strcpy(opcode, "0111");
//聊天记录,插入数据库
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO record(ufrom, uto, msg, msg_id) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, passwd);
strcat(sql, "', '");
strcat(sql, msg);
strcat(sql, "', 1)");
//printf("%s", sql);
mysql_query(conn, sql);
} else {
strcpy(opcode, "0112");
}
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, username, passwd, msg);
//len = send(cli_fd[fp], buf, strlen(buf), 0);
}
len = send(cli_fd[index], buf, strlen(buf), 0);
if (len > 0) {
//printf("消息:%s\t发送成功,共发送了%d个字节!\n",buf, len);
}
}else if (len < 0) {
//出错
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno)); 
} else {//断开连接
printf("对方退出了,聊天终止\n");
char db_index[5];
//删除下线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "delete from isline where cli_id='");
//strcat(sql, username);
//strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "'");
//printf("%s", sql);
mysql_query(conn, sql);
close(cli_fd[index]);
cli_fd[index] = -1;
bzero(&cli_addr[index], sizeof(struct sockaddr_in));
//break;
}
}
          }
}
}
//break;

} else {
exit(3);
}
}
    }
    /* close connection */
    mysql_free_result(res);
    mysql_close(conn);
    close(sockfd);
    return 0;
}

#2


各位高手,
我想实现一个服务器,多个客户端之间通讯,由服务器转发客户端的信息
客户端A发送消息格式为[B haoa] ,则服务器把消息转发给B,消息haoa ,现在可以实现服务器接受客户端A发过来的信息,能到数据库中找到B,可是服务器的孙子进程无法将信息发送到B,这怎么办 

#3


同步队列加select 模型

#4


broadcast

#5


具体怎么实现,能细说吗,救急

#6


聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.

#7


引用 6 楼  的回复:
聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.


最简单的就是自己实现一个简单的mysql proxy,也就是短链接+线程池的架构。
可以做在聊天室进程里,也可以单独做在一个进程里。
一般这种小功能就做在聊天室进程里就可以了,mysql线程池,select+pipe任务分发,每个connection一样有pipe用于结果通知.

主线程实现就是状态机+epoll就可以.

#8


高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教

#9


引用 8 楼  的回复:
高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教


多进程没法良好的交互啊, 信息共享可以共享内存, 但进程间事件通知太麻烦了, 得多编码不少东西才能实现.

比如A进程里的a给B进程的b发信息,怎么发?只能再做个进程IPC把消息转过去. 在线用户信息怎么共享? 共享内存.

#10


感谢楼上

#1



int ppid = fork();
if (ppid == 0) {
if (fork() == 0) {
while (1) {
int save_index = j;
// 把集合清空
FD_ZERO(&rfds);
// 把标准输入句柄0加入到集合中 
//FD_SET(0, &rfds);
maxfd = 0;
// 把当前连接句柄cli_fd[index]加入到集合中 
for (index=0; index<MAXC; index++) {
if (cli_fd[index]>=0) {
FD_SET(cli_fd[index], &rfds);
if (cli_fd[index] > maxfd) {
maxfd = cli_fd[index];
}
}
}
// 设置最大等待时间
tv.tv_sec = 1;
tv.tv_usec = 0;
// 开始等待
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
for (index=0; index<MAXC; index++) {
if (cli_fd[index]>=0) {
if (retval == -1) {
printf("将退出,select出错! %s", strerror(errno));
close(cli_fd[index]);
bzero(&cli_addr[index], sizeof(struct sockaddr_in));
cli_fd[index] = -1;
break;
} else if (retval == 0) {
// printf("没有任何消息到来,用户也没有按键,继续等待……\n");
continue;
} else {
if (FD_ISSET(cli_fd[index], &rfds)) {
// 当前连接的socket上有消息到来则接收对方发过来的消息并显示 
bzero(buf, MAXBUF + 1);
// 接收客户端的消息
len = recv(cli_fd[index], buf, MAXBUF, 0);
if (len > 0) {
//printf("接收消息成功:'%s',共%d个字节的数据\n",buf, len);
int i=0;
opcode[0] = buf[0];
opcode[1] = buf[1];
opcode[2] = buf[2];
opcode[3] = buf[3];
opcode[4] = '\0';
bspace(username, sizeof(username));
bspace(passwd, sizeof(passwd));
for (i=0; i<20; i++) {
username[i] = buf[i+4];
}
username[19] = '\0';
rtrim(username);
for (i=0; i<20; i++) {
passwd[i] = buf[i+24];
}
passwd[19] = '\0';
rtrim(passwd);
for (i=44; i<sizeof(buf); i++) {
temp_buf[i-44] = buf[i];
}
temp_buf[sizeof(buf)-45] = '\0';
strncpy(msg, temp_buf, strlen(temp_buf));
trim(msg);
printf("%d", index);
if (!strncmp(opcode, "0000", 4)) {
printf("注册user=%s,passwd=%s\n", username, passwd);
bzero(opcode, sizeof(opcode));
//此处需要校验用户是否存在,返回对应的opcode
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM user where name='");
strcat(sql, username);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
if (record_nums > 0) {
//已有
strncpy(opcode, "0002", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
//可用
//添加用户
char db_index[5];
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO user(name, passwd) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, passwd);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

//添加在线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO isline(name, cli_id) values('");
strcat(sql, username);
strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

strncpy(opcode, "0001", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
}
} else if (!strncmp(opcode, "0010", 4)) {
//printf("登录user=%s,passwd=%s\n", username, passwd);
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM isline where name='");
strcat(sql, username);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
strncpy(opcode, "0013", 4);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
strcpy(sql, "SELECT * FROM user where name='");
strcat(sql, username);
strcat(sql, "' and passwd='");
strcat(sql, passwd);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
char db_index[5];
//添加在线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO isline(name, cli_id) values('");
strcat(sql, username);
strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "')");
//printf("%s", sql);
mysql_query(conn, sql);

//登录成功
strncpy(opcode, "0011", 4);
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, "biaobiao", username, "shoudao");
} else {
//登录失败
strncpy(opcode, "0012", 4);
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, "", "", "");
}
}
} else if (!strncmp(opcode, "0100", 4)) {
//printf("公聊user=%s,msg=%s\n", username, temp_buf);
bzero(opcode, sizeof(opcode));
strcpy(opcode, "0101");
//聊天记录,插入数据库
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO record(ufrom, msg, msg_id) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, msg);
strcat(sql, "', 2)");
//printf("%s", sql);
mysql_query(conn, sql);

bspace(buf, MAXBUF + 1);
get_string(buf, opcode, username, "", msg);
} else if (!strncmp(opcode, "0110", 4)) {
//get cli_fd[index] 向对应的用户发送信息
//printf("私信user=%s,msg=%s\n", username, temp_buf);
bzero(opcode, sizeof(opcode));

memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "SELECT * FROM isline where name='");
strcat(sql, passwd);
strcat(sql, "'");
//printf("%s", sql);
if (mysql_query(conn, sql)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn); 
int record_nums = 0;
record_nums = (int)mysql_num_rows(res);
bzero(opcode, sizeof(opcode));
if (record_nums > 0) {
strcpy(opcode, "0111");
//聊天记录,插入数据库
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "INSERT INTO record(ufrom, uto, msg, msg_id) values('");
strcat(sql, username);
strcat(sql, "', '");
strcat(sql, passwd);
strcat(sql, "', '");
strcat(sql, msg);
strcat(sql, "', 1)");
//printf("%s", sql);
mysql_query(conn, sql);
} else {
strcpy(opcode, "0112");
}
bspace(buf, MAXBUF + 1);
get_string(buf, opcode, username, passwd, msg);
//len = send(cli_fd[fp], buf, strlen(buf), 0);
}
len = send(cli_fd[index], buf, strlen(buf), 0);
if (len > 0) {
//printf("消息:%s\t发送成功,共发送了%d个字节!\n",buf, len);
}
}else if (len < 0) {
//出错
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno)); 
} else {//断开连接
printf("对方退出了,聊天终止\n");
char db_index[5];
//删除下线用户
memset(sql, '\0', sizeof(sql));
/* send SQL query */
strcpy(sql, "delete from isline where cli_id='");
//strcat(sql, username);
//strcat(sql, "', '");
itoa(save_index, db_index);
strcat(sql, db_index);
strcat(sql, "'");
//printf("%s", sql);
mysql_query(conn, sql);
close(cli_fd[index]);
cli_fd[index] = -1;
bzero(&cli_addr[index], sizeof(struct sockaddr_in));
//break;
}
}
          }
}
}
//break;

} else {
exit(3);
}
}
    }
    /* close connection */
    mysql_free_result(res);
    mysql_close(conn);
    close(sockfd);
    return 0;
}

#2


各位高手,
我想实现一个服务器,多个客户端之间通讯,由服务器转发客户端的信息
客户端A发送消息格式为[B haoa] ,则服务器把消息转发给B,消息haoa ,现在可以实现服务器接受客户端A发过来的信息,能到数据库中找到B,可是服务器的孙子进程无法将信息发送到B,这怎么办 

#3


同步队列加select 模型

#4


broadcast

#5


具体怎么实现,能细说吗,救急

#6


聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.

#7


引用 6 楼  的回复:
聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.


最简单的就是自己实现一个简单的mysql proxy,也就是短链接+线程池的架构。
可以做在聊天室进程里,也可以单独做在一个进程里。
一般这种小功能就做在聊天室进程里就可以了,mysql线程池,select+pipe任务分发,每个connection一样有pipe用于结果通知.

主线程实现就是状态机+epoll就可以.

#8


高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教

#9


引用 8 楼  的回复:
高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教


多进程没法良好的交互啊, 信息共享可以共享内存, 但进程间事件通知太麻烦了, 得多编码不少东西才能实现.

比如A进程里的a给B进程的b发信息,怎么发?只能再做个进程IPC把消息转过去. 在线用户信息怎么共享? 共享内存.

#10


感谢楼上