免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3067 | 回复: 3
打印 上一主题 下一主题

[C] 求助linux下利用多线程和socket的多用户聊天室的问题? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-15 18:18 |只看该作者 |倒序浏览
(网上下了别人的例子想学习下,在其基础上小改下,运行时出问题:开一个client端连接server端,收发信息正常,再开一个client端,前一个client端失效,再开第三个,前两个失效)
主要变量定义:
int client[20]存放用户套接字标识符;
int sockfd表示服务器本地套接字;
char buf[ ]作为共享接收消息缓冲区;

server端:
两个线程:线程1 收client端信息,线程2 发信息给client端

client端:
两个进程:父进程 发信息给server端,子进程 收server端信息

程序如下:
client端:
//包含工程所需的头文件
#include<stdio.h>
#include<netinet/in.h>  //定义数据结构sockaddr_in
#include<sys/socket.h>  //提供socket函数及数据结构
#include<sys/types.h> //数据类型定义
#include<string.h>
#include<stdlib.h>
#include<netdb.h>
#include<unistd.h>
#include<signal.h>
#include<time.h>
int main(int argc, char *argv[])
{
    struct sockaddr_in clientaddr;//定义地址结构
    pid_t pid;
    int clientfd,sendbytes,recvbytes;//定义客户端套接字
    struct hostent *host;
    char *buf,*buf_r;
    /*
    if(argc < 4)
    {
        printf("usage:\n");
        printf("%s host port name\n",argv[0]);
        exit(1);
    }
    */
    //host = gethostbyname(argv[1]);
    if((clientfd = socket(AF_INET,SOCK_STREAM,0)) == -1)  //创建客户端套接字
    {
        perror("socket\n");
        exit(1);
    }
    //绑定客户端套接字
    clientaddr.sin_family = AF_INET;
    //clientaddr.sin_port = htons((uint16_t)atoi(argv[2]));
    clientaddr.sin_port = htons((uint16_t)atoi("3491"));
    inet_pton(AF_INET, "127.0.0.1", &clientaddr.sin_addr);
    //clientaddr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(clientaddr.sin_zero),0);
    if(connect(clientfd,(struct sockaddr *)&clientaddr,sizeof(struct sockaddr)) == -1) //连接服务端
    {
        perror("connect\n");
        exit(1);
    }
    buf=(char *)malloc(120);
    memset(buf,0,120);
    buf_r=(char *)malloc(100);

    if( recv(clientfd,buf,100,0) == -1)
    {
        perror("recv:");
        exit(1);
    }
    printf("\n%s\n",buf);

    pid = fork();//创建子进程
    while(1)
    {
        if(pid > 0){
            //父进程用于发送信息

            //get_cur_time(time_str);

            //strcpy(buf,argv[3]);
            //strcpy(buf,argv[1]);
            strcpy(buf,"tuta");
            strcat(buf,":");
            memset(buf_r,0,100);
            //gets(buf_r);
            fgets(buf_r,100,stdin);
            strncat(buf,buf_r,strlen(buf_r)-1);
            //strcat(buf,time_str);
            //printf("---%s\n",buf);
            if((sendbytes = send(clientfd,buf,strlen(buf),0)) == -1)
            {
                perror("send\n");
                exit(1);
            }
        }
        else if(pid == 0)
        {
            //子进程用于接收信息
            memset(buf,0,100);
            if(recv(clientfd,buf,100,0) <= 0)
            {
                perror("recv:");
                close(clientfd);
                raise(SIGSTOP);
                exit(1);
            }
            printf("%s\n",buf);
        }
        else
            perror("fork");
    }
    close(clientfd);
    return 0;   
}

server端:
//包含工程所需的头文件
#include<stdio.h>   
#include<stdlib.h>
#include<sys/types.h>  //数据类型定义
#include<sys/stat.h>
#include<netinet/in.h>  //定义数据结构sockaddr_in
#include<sys/socket.h>  //提供socket函数及数据结构
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/ipc.h>
#include<errno.h>
#include<sys/shm.h>
#include<time.h>
#include <pthread.h>
#define PERM S_IRUSR|S_IWUSR  
#define MYPORT 3491  //宏定义定义通信端口
#define BACKLOG 10 //宏定义,定义服务程序可以连接的最大客户数量
#define WELCOME "|----------Welcome to the chat room! ----------|"  //宏定义,当客户端连接服务端时,想客户发送此欢迎字符串
//转换函数,将int类型转换成char *类型

pthread_mutex_t mut;
pthread_t thread[20];
char *buf;

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);
}
//创建共享存储区
key_t shm_create()
{
    key_t shmid;
    //shmid = shmget(IPC_PRIVATE,1024,PERM);
    if((shmid = shmget(IPC_PRIVATE,1024,PERM)) == -1)
    {
        fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno));
        exit(1);
    }
    return shmid;
}
//端口绑定函数,创建套接字,并绑定到指定端口
int bindPort(unsigned short int port)
{  
    int sockfd;
    struct sockaddr_in my_addr;
    sockfd = socket(AF_INET,SOCK_STREAM,0);//创建基于流套接字
    my_addr.sin_family = AF_INET;//IPv4协议族
    my_addr.sin_port = htons(port);//端口转换
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero),0);

    if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1)
    {
        perror("bind");
        exit(1);
    }
    printf("bind success!\n");
    return sockfd;
}

void *thread1(void *fd[])
{
    char *time_str, *temp, *w_addr, *r_addr;
    int recvbytes;
    time_str=(char *)malloc(20);
    temp = (char *)malloc(255);
    //buf = (char *)malloc(255);
    //memset(buf,0,255);
    send(fd[0],WELCOME,strlen(WELCOME),0);//发送问候信息
    while(1)
    {
      
        if((recvbytes = recv(fd[0],buf,255,0)) <= 0)
        {
            perror("recv1");
         
            close(fd[0]);
            raise(SIGKILL);
            exit(1);
        }
        if(strstr(buf, "quit") != 0){
            break;
        }
        sleep(2);
    }
    printf("------------------------------\n");
    free(buf);
    close(fd[0]);
    return 0;
}

void *thread2(void *fd[])
{
    char *time_str, *tmp;
    time_str = (char *)malloc(20);
    tmp = (char *)malloc(255);
    while(1)
    {
        if(strcmp(tmp, buf) == 0){
            continue;
        }
        printf(" %s\n",buf);
        if(send(fd[0],buf,strlen(buf),0) == -1)
        {
            perror("send");
        }
        strcpy(tmp, buf);
    }
    printf("------------------------------\n");
    free(buf);
    close(fd[0]);
}

void multi_pthread(int m, int *store[])
{
    pthread_mutex_init(&mut,NULL);
    int temp;
    memset(&thread, 0, sizeof(thread));

    if((temp = pthread_create(&thread[m], NULL, thread1, store)) != 0){
        printf("线程创建失败!\n");
    }
    else
        printf("线程1被创建\n");

    if((temp = pthread_create(&thread[m+1], NULL, thread2, store)) != 0){
        printf("线程创建失败!\n");
    }
    else
        printf("线程2被创建\n");
}

int main(int argc, char *argv[])
{
    int sockfd,clientfd,sin_size,recvbytes,client_fd[10],i=0,k; //定义监听套接字、客户套接字
    int *store[2];
    socklen_t theiraddr_len;
    char *r_addr, *w_addr, *temp, *time_str;//="\0"; //定义临时存储区
    struct sockaddr_in their_addr;  //定义地址结构
    key_t shmid;
    memset(client_fd,0,10);

    buf = (char *)malloc(255);

    shmid = shm_create(); //创建共享存储区

    temp = (char *)malloc(255);
    time_str=(char *)malloc(20);
    sockfd = bindPort(MYPORT);//绑定端口
    while(1)
    {     
        if(listen(sockfd,BACKLOG) == -1)//在指定端口上监听
        {
            perror("listen");
            exit(1);
        }
        printf("listening......\n");
        theiraddr_len = sizeof(their_addr);
        if((clientfd = accept(sockfd,(struct sockaddr*)&their_addr,&theiraddr_len)) == -1)//接收客户端连接
        {
            perror("accept");
            exit(1);
        }else{
            while (1){
                if((clientfd != client_fd[i]) && (client_fd[i+1] == 0)){
                    client_fd[i+1] = clientfd;
                    k = i+1;
                    store[0] = client_fd[i+1];
                    store[1] = shmid;
                    multi_pthread(k,store);
                    //pthread_join(thread[k],NULL);
                    break;
                }
                i++;
            }
        }
    }
    return 0;
}



论坛徽章:
0
2 [报告]
发表于 2013-05-15 18:24 |只看该作者
菜鸟一枚,是否存在数据冲突?但我server端分两个线程处理信息的收发 ,client端有两个父子进程处理信息的收发 求解?需要贴运行时出的问题吗?

论坛徽章:
0
3 [报告]
发表于 2013-05-15 20:34 |只看该作者
int *store[2];
store未开辟空间

论坛徽章:
0
4 [报告]
发表于 2013-05-29 15:12 |只看该作者
原因找到了,这里没人了,唉!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP