#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,这怎么办
我想实现一个服务器,多个客户端之间通讯,由服务器转发客户端的信息
客户端A发送消息格式为[B haoa] ,则服务器把消息转发给B,消息haoa ,现在可以实现服务器接受客户端A发过来的信息,能到数据库中找到B,可是服务器的孙子进程无法将信息发送到B,这怎么办
#3
同步队列加select 模型
#4
broadcast
#5
具体怎么实现,能细说吗,救急
#6
聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.
#7
最简单的就是自己实现一个简单的mysql proxy,也就是短链接+线程池的架构。
可以做在聊天室进程里,也可以单独做在一个进程里。
一般这种小功能就做在聊天室进程里就可以了,mysql线程池,select+pipe任务分发,每个connection一样有pipe用于结果通知.
主线程实现就是状态机+epoll就可以.
#8
高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教
#9
多进程没法良好的交互啊, 信息共享可以共享内存, 但进程间事件通知太麻烦了, 得多编码不少东西才能实现.
比如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,这怎么办
我想实现一个服务器,多个客户端之间通讯,由服务器转发客户端的信息
客户端A发送消息格式为[B haoa] ,则服务器把消息转发给B,消息haoa ,现在可以实现服务器接受客户端A发过来的信息,能到数据库中找到B,可是服务器的孙子进程无法将信息发送到B,这怎么办
#3
同步队列加select 模型
#4
broadcast
#5
具体怎么实现,能细说吗,救急
#6
聊天室很明显必须单进程单线程才是合理的, 至于数据库查询问题, 应该找一款提供异步接口的Mysql proxy, 而不是阻塞mysql查询.
#7
最简单的就是自己实现一个简单的mysql proxy,也就是短链接+线程池的架构。
可以做在聊天室进程里,也可以单独做在一个进程里。
一般这种小功能就做在聊天室进程里就可以了,mysql线程池,select+pipe任务分发,每个connection一样有pipe用于结果通知.
主线程实现就是状态机+epoll就可以.
#8
高手,我刚学linux下的C编程,请见谅。
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教
按我现在这样的思想可以继续完成吗
怎么实现转发
代码里有严重的方法错误吗,求教
#9
多进程没法良好的交互啊, 信息共享可以共享内存, 但进程间事件通知太麻烦了, 得多编码不少东西才能实现.
比如A进程里的a给B进程的b发信息,怎么发?只能再做个进程IPC把消息转过去. 在线用户信息怎么共享? 共享内存.
#10
感谢楼上