Linux C 网络编程 急~~~~~~~~~~~~~~~~~~

GoodLuckMax 2012-03-19 11:04:39
用多线程实现的的一个多人聊天室....
用数组储存用户
struct user
{
int id;
char name[USER_NAME_LEN];
char password[USER_PASS_LEN];
char *p_chatlog;
struct sockaddr user_addr;
int socket_fd;
};...
server创建了一个监听进程一直accept...
运行时错误:一个用户登录可以完美操作,程序没任何问题 但是当第二个用户进来 马上server就报recv:socket operation on non-socket...
我检查了一下,第一个用户进来的时候usr[user_count].socket_fd=5 这是正常的吧..
第二个用户一进来 第一个用户的socket_fd就变成6了,而第二个用户的socket_fd=0...
就像请问一下是什么原因造成的...
这是我的毕业设计,蛋疼死了...纠结了几天了..
下面是几个相关的函数... 还有 我user_count开始是-1;
另外里面com_打头的方法是我简单封装了一下的,跟原方法没什么区别的..
全局变量:
struct sockaddr_in server_addr;
pthread_t listening_thread;
pthread_t client_thread[MAX_USER_CONN];
struct user usr_array[MAX_USER_CONN];
struct user usr_list[MAXSIZE];
int user_list_count;
int server_fd;
int user_count=-1;


int judge_client_action()
{
int receive_bytes;
struct message flag_msg;
bzero(&flag_msg,MSG_LEN);
printf("usr.socket_fd:%d",usr_array[user_count+1].socket_fd);
receive_bytes=com_recv(usr_array[user_count+1].socket_fd,&flag_msg,MSG_LEN,0);
flag_msg.content[receive_bytes]='\0';
switch(flag_msg.flag)
{
case 2 : user_login(flag_msg);
break;
case 3 : user_regist(flag_msg);
break;
default: login_regist_error();
break;
}
}

void pthread_listen()
{
printf("[INFO]Listening Thread is Strating...\n");
while(1)
{
if(listen(server_fd,BACKLOG)==-1)
{
perror("[ERROR INFO]listen");
com_exit(1);
}

socklen_t sin_size=sizeof(struct sockaddr_in);

if((usr_array[user_count+1].socket_fd=accept(server_fd,(struct sockaddr*) &usr_array[user_count+1].user_addr,&sin_size))==-1)
{
perror("[ERROR INFO]socket");
com_exit(1);
}
printf("usr_array[user_count+1].socket_fd:%d\n",usr_array[user_count+1].socket_fd);
printf("[INFO]Some One Connected...\n");

if(pthread_create(&client_thread[user_count+1],NULL,(void *)client_handle,NULL)!=0)
{
perror("pthread_create listening_thread");
exit(1);
}
}
}

void client_handle()
{
judge_client_action();
user_count++;
struct message msg;
printf("break point\n");
strcpy(msg.content,"[INFO]You Are Connected,It's Server's Feed Back...\n");
com_send(usr_array[user_count].socket_fd,&msg,MSG_LEN,0);
printf("[INFO]Current User Count:%d\n",user_count+1);
receive_msg((struct user)usr_array[user_count]);
}


void receive_msg(struct user r_usr)
{
while(1)
{
int receive_bytes;
struct message msg;
receive_bytes=com_recv(r_usr.socket_fd,&msg,MSG_LEN,0);
msg.content[receive_bytes]='\0';
int i=0;
while(i<=user_count)//send client to client
{
com_send(usr_array[i].socket_fd,&msg,MSG_LEN,0);
i++;
}
}
}

int main()
{
socket_init();
init_user_list();
if((pthread_create(&listening_thread,NULL,(void *)pthread_listen,NULL))!=0)
{
perror("pthread_create listening_thread");
exit(1);
}
//sleep(1);
printf("[INFO]Current User Count:%d\n",user_count+1);
while(1)//listening the server message to client
{
char send_msg[MAXSIZE];
scanf("%s",send_msg);
struct message msg;
strcpy(msg.content,send_msg);
int i=0;
while(i<=user_count)
{
com_send(usr_array[i].socket_fd,&msg,MSG_LEN,0);
i++;
}
}
}



...全文
387 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
luciferisnotsatan 2012-03-22
  • 打赏
  • 举报
回复
我检查了一下,第一个用户进来的时候usr[user_count].socket_fd=5 这是正常的吧..
第二个用户一进来 第一个用户的socket_fd就变成6了,而第二个用户的socket_fd=0...


更具你的描述和代码,推测为:

在第一个用户accept并printf出fd 和 程序运行到user_count++;之间,第二个用户连了上来,此时user_count的值还没加1,到时accept的值又赋给了第一个元素。所以你的第一个用户变成了6,而第二个还是0(全局变量初始化为0)

accept后就可以user_count++了。但这要还是不保险。你该把client_handle所需的fd当参数传入,而不是用全局变量。
luciferisnotsatan 2012-03-22
  • 打赏
  • 举报
回复
accept返回 0?fd 0通常是标准输入,你的代码里没见有哪关闭0。
说起来,代码里,用完的fd都没close。
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
其实程序逻辑很简单: main()开始.创建一个listen进程,用于监听.在listen里面如果accetp到用户就再创建一个线程(意思就是在listen线程里面创建线程).
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 luciferisnotsatan 的回复:]

user_count没加锁。
这代码看着挺乱的。

用到socket,多线程,没学过C。还是那句,为啥毕设选个你压根没学过的东西来做?
[/Quote]
这个伤心事就不要提了嘛,我自己造的孽....说实话代码确实很乱...连C的hello world都没写过就直接做这个...

现在问题好像就在accept上,为什么新的用户进来accept返回0.
就像我之前说的:第一个用户进来的时候usr[user_count].socket_fd=5 这是正常的吧..
第二个用户一进来 第一个用户的socket_fd就变成6了,而第二个用户的socket_fd=0...
luciferisnotsatan 2012-03-22
  • 打赏
  • 举报
回复
user_count没加锁。
这代码看着挺乱的。

用到socket,多线程,没学过C。还是那句,为啥毕设选个你压根没学过的东西来做?
luciferisnotsatan 2012-03-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 gaoleiidf4 的回复:]

引用 6 楼 qq120848369 的回复:
review你的代码,认为你的代码是完全错的, 找到BUG后推倒重写。

我刚学C五天不到,语法都没看过,直接就做这个聊天室,压力很大,因为是毕业设计..
能给我讲讲代码完全错在哪里吗 ?
[/Quote]
为啥你的毕设要用没学过的C来做????
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 zhao4zhong1 的回复:]

要使用线程池,不要动态创建销毁线程。
特供调试多线程程序使用:
C/C++ code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#i……
[/Quote]
想请问一下,如果不使用线程池会造成什么后果呢..就是说我这里没使用线程池创建线程有错误 ??
我是在服务器listen线程里面再创建每一个client的recv_msg进程(线程里创建线程)....这样会造成逻辑错误吗??
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 sundayx 的回复:]

在client_handle这个线程还未处理user_count++时,可能会有别的client连接进来,这样在accept时usr_array[user_count+1]中的user_count还并未加1,覆盖了原来的socket_fd.
[/Quote]
您说的很对,我这里逻辑确实有点问题.
这里先抛开您的问题(您提出来的我后来会改正):当一个用户登录成功后再次accept第二个用户时出错..这个时候user_count已经++了..
这才是我没搞懂的地方...既然++了..为什么server不能正常accetp第二个用户...
麻烦您稍微帮我看看哪里出错了,刚学C几天,对很多东西都不是很清楚..谢谢了..
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
这是什么情况,都给了分的啊 ? 怎么都没分...
难道服务器还没更新还是正在审核?
slight 2012-03-22
  • 打赏
  • 举报
回复
虽然不会,但是顶了!
GoodLuckMax 2012-03-22
  • 打赏
  • 举报
回复
结贴了,谢谢各位的帮助,谢谢所有人...特别感谢:路西法不是撒旦
30楼所说的正是我的问题..
其实我之前一直也是这种推测,但每次看了代码,又推翻了自己...今天认真想了一下,才找到问题..
其实是这么小个问题,应该自己解决的...本来就认为,把这么多代码发上来,一般都不会有人看的...
但愿我能顺利毕业吧....
最后再次感谢大家.....
sundayX 2012-03-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 gaoleiidf4 的回复:]

引用 11 楼 hlyces 的回复:

user_count
在accept后马上自增,不要在后面才自增。

我做了登录功能的,所以accept之后不能user_count++,要等到登录成功之后才能++
[/Quote]
既然是登录成功后才能++,那使用usr_array时就不要用usr_count作为索引。可以在accept后就执行usr_count++,若用户登录验证失败,将socket_fd改成-1,然后断开连接。在获取当前用户数时计算usr_array中socket_fd不等于-1的个数。在填充user结构时,填在第一个sockfd_fd为-1的位置。
sundayX 2012-03-21
  • 打赏
  • 举报
回复
在client_handle这个线程还未处理user_count++时,可能会有别的client连接进来,这样在accept时usr_array[user_count+1]中的user_count还并未加1,覆盖了原来的socket_fd.
GoodLuckMax 2012-03-21
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 nanjingnew4 的回复:]
建议你单步跟踪下socketfd,看看他的值怎么变的
[/Quote]
单步跟踪是什么意思啊...
socketfd就是accept了新用户之后就变了...accept是系统函数,没发看到是怎么变的...
赵4老师 2012-03-21
  • 打赏
  • 举报
回复
要使用线程池,不要动态创建销毁线程。
特供调试多线程程序使用:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define _vsnprintf vsnprintf
#endif
//Log{
#define MAXLOGSIZE 100000000
#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
char logstr[16000];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
struct tm *now;
struct timeb tb;

if (NULL==pszFmt||0==pszFmt[0]) return;
if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0;
ftime(&tb);
now=localtime(&tb.time);
sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec );
sprintf(mss,"%03d",tb.millitm);
printf("%s %s.%s %s",datestr,timestr,mss,logstr);
flog=fopen(logfilename1,"a");
if (NULL!=flog) {
fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
if (ftell(flog)>MAXLOGSIZE) {
fclose(flog);
if (rename(logfilename1,logfilename2)) {
remove(logfilename2);
rename(logfilename1,logfilename2);
}
flog=fopen(logfilename1,"a");
if (NULL==flog) return;
}
fclose(flog);
}
}
void Log(const char *pszFmt,...) {
va_list argp;

Lock(&cs_log);
va_start(argp,pszFmt);
LogV(pszFmt,argp);
va_end(argp);
Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
int i;
#ifdef WIN32
InitializeCriticalSection(&cs_log);
#else
pthread_mutex_init(&cs_log,NULL);
#endif
for (i=0;i<10000;i++) {
Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
}
#ifdef WIN32
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_log);
#endif
return 0;
}
nanjingnew4 2012-03-20
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 gaoleiidf4 的回复:]
还没人啊?
[/Quote]
建议你单步跟踪下socketfd,看看他的值怎么变的
GoodLuckMax 2012-03-20
  • 打赏
  • 举报
回复
还没人啊?
GoodLuckMax 2012-03-19
  • 打赏
  • 举报
回复
GoodLuckMax 2012-03-19
  • 打赏
  • 举报
回复
自己顶下, 求高人解决..
g52313035 2012-03-19
  • 打赏
  • 举报
回复
路过帮顶一下吧,希望有高人为你解答
加载更多回复(13)

69,372

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧