- 论坛徽章:
- 0
|
从八月20好左右开始,我们小组里面好几个成员准备编写一个基于字符界面的聊天工具。
主要是对假期所学知识的一个总结。我负责服务器端的编写。但是在编写过程中也遇到了
很多问题。首先是是对接受到客户端发送消息的解析。刚开始解析时就出现了问题。由于
通过socket接受到的是字符串信息。我们之间的协议中有int类型和char类型之间的转换。
下面先介绍 strtok 、atoi、fcvt 等函数,他们的用法在下面的函数中有用到
1、strtok
原型:extern char *strtok(char *s, char *delim);
用法:#include
功能:分解字符串为一组标记串。s为要分解的字符串,delim为分隔符字符串。
函数说明:
首次调用时,s必须指向要分解的字符串,随后调用要把s设成NULL。
strtok在s中查找包含在delim中的字符并用NULL('\0')来替换,直到找遍整个字符串。
返回指向下一个标记串。当没有标记串时则返回空字符NULL。
2、atoi
函数名: atoi
功 能: 把字符串转换成长整型数
用 法: int atoi(const char *nptr);
函数说明:
atoi()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,
而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回。
3、fcvt
函数名: fcvt
功 能: 把一个浮点数转换为字符串
用 法: char *fcvt(double value, int ndigit, int *decpt, int *sign);
函数说明:
alue为要转换的实数,ndigit为要保留的小数点后的位数,*decpt,*sign 为两个整形的
指针变量,基本上没多大用处
在刚开始时,用C语言的强制类型转换可以将char类型的变量转换为int类型。可是我想用int
类型转换为char类型时切出现了问题,for example:
int a=48;
char b;
b = (char) a;
printf("%d,%d\n",b,b);
前者的输出结果和后者的输出结果肯定是不一样的,我以为这样自就已经强制转换完成。但是当
我再把b赋值给一个字符串数组时有一个警告:
char msg[1024];
bzero(msg.sizeof(msg));//清空msg里面的东西,让mag==NULL
strcpy(msg,b);
执行上边的语句出现警告,因为b任然是一个int类型的变量,int类型变量作战的字节数大于char类型
于是我找到了fcvt函数,还是不行,一个办法就是先把int型的变量转换为double型的变量后再调用
fcvt函数,这样自就可以把int类型的变量转换为char类型的变量了。
一下的是我们还没完成的服务器端,其中还有很多的问题。
1、服务器端现在能够接受客户端发送过来的消息,并把他解析后通过管道发发送给父一个进程,父进程
也能接受子进程发送过来的消息,并把他解析。解析后发送给客户端是,不能发送。后来通过孔建军学长
的解释明白了不能发送数据的原因,这一点有待后面的修改。
2、有一个用户列表是通过文件来保存的,处于循环的时候,进程几乎一直都在读取列表,感觉效率很地下,
还有就是在客户端退出的时候,其保存在列表里面的信息并没有删除。
3、在文件的存储结构上面,采用的是fprintf(),fscanf()和结果体数组,这样自很麻烦,每次都得从
文件里面读取所有的信息,然后在写入文件。这一点有待改进。
基本的问题就是上面这些,下面是还没完成的服务器端的代码,有时间,有兴趣的朋友们可以看一下帮忙改进
改进后可以E-Mail to me: xypmdxx@gmail.com
//server.c
#include
#include
#include
#include
#include
#include
#include
#define MAX 8
#define BUF_MAX 1024
struct user_struct {
int id;
int connect_fd;
char name[20];
in_addr_t ip_addr;
int port;
int status; //1 online 0 leave
}users[MAX];
struct count_struct{
int num_max;
}count;
int process_option()
{
//getopt_long();
//解析命令行参数,得到server_ip,port,用户最大数目等参数,对-v -h 等常见选项做解析
/*if( argc >1 )
serverIP=argv[1];
if (argc >2 )
Port=atoi(argv[2]);
if ((socket_fd=socket(AF_INET,SOCK_STREAM,0)) sin_family = AF_INET;
server_addr->sin_port = htons(port);
server_addr->sin_addr.s_addr = inet_addr(server_ip);
if ((bind(*socket_fd, (struct sockaddr *)server_addr, sizeof(*server_addr))) 1)
{
fscanf(fp, "%d ", &count.num_max);
for(i=0; i<user_num -1; i++)
fscanf(fp ,"%d %d %d %s ", &users.id, &users.connect_fd, &users.status, &users.name);
count.num_max ++;
save_num();
fclose(fp);
}
//分配用户账号1~MAX,并写入文件或存放在结构体链表/字符串数组里这里建议写入文件,这样就可以简化进程间通信的复杂度
users[user_num].id = user_num;
users[user_num].connect_fd = connect_fd;
users[user_num].status = 1;
gethostname(users[user_num].name, sizeof(users[user_num].name));
if((fp=fopen(".user.txt","at"))==NULL)
{
printf("不能打开此文件!\n");
exit(0);
}
fprintf(fp,"%d %d %d %s ", users[user_num].id, users[user_num].connect_fd, users[user_num].status, users[user_num].name);
fclose(fp);
//在这里也讲每个用户对应的connect_fd存放在一个数组中便于主进程发送信息
if(fork()==0)
{
printf("I am service_client [%d]!\n",user_num);
service_client(&connect_fd,fd,user_num);
break;
}
user_num++;
}
}
else
receive_data(fd,users);
wait();
return 0;
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/74012/showart_1163199.html |
|