Ubuntu环境下基于Socket通信的网络聊天系统

在Linux环境下,利用Socket通信实现网络聊天程序,主要包括以下功能:

(1)系统各菜单功能界面、聊天界面的显示

(2)用户的注册、登录(手机号注册,合格性检测,重复性检测),注册后创建用户文件夹

(3)可支持好友管理(好友列表在线显示、增删查,网络传输文件),账户管理(修改信息,权限变更(创新可调用MD5库文件)

(3)聊天方式分群聊和私聊两种方式,群聊可管理员设置禁言,代码实现禁言单用户,全员禁言代码类同(创新可加入自然语言检测,实现敏感词监督)

(4)保存聊天记录,代码实现保存私聊记录,群聊记录保存类同

(5)实现客户端之间网络传输文件

服务器每接上一个客户端,启动一个线程;

客户端创建收发线程与服务器交互。

Server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <memory.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <time.h>
#include <malloc.h>
#include <sys/stat.h>
#include <termios.h>

#define NUM 1024
#define SIZE sizeof(cliMesg)  //结构体cliMesg的大小
typedef long long ll;


//账户类
typedef struct client_message
{
    char id[20];         //每个账号唯一id,  手机号
    char passwd[20];	 //账号密码
    char name[50];		 //账号昵称
    char hy[100][20];	 //好友列表,最大100个
    int hys;             //好友数量
    int online;          //0不在线, 1在线
    int fd;              //存放客户端成功连接后accept产生的新的套接字,  不在线为-5
    int chatroom;		 //存放是否打开了双人聊天室,打开为1 ,  没打开为0
    int admin;          //管理员权限  -1禁言 - 踢出不能再进
    //bMesg status;  //禁言
    long ed_time;
    struct client_message *next;	 //下一条链表的首地址

}cliMesg;

//信息类
typedef struct friend_message
{
    char rid[20];               //收信息的人
    char sid[20];               //发信息的人
    int type;                   //信息类型 ,  好友请求1 ,  私聊信息 2 , 好友请求回复信息3 ,  文件传输4 , 文件回复5
    char mesg[1024];            //信息
    char fname[1024];           //文件名
    struct friend_message * next;//下一条信息的首地址
}friMesg;

cliMesg *head=NULL;
friMesg *head1=NULL; 
int count =0;   //账号数量
int urev_count=0;   //未发送的信息

//创建账号信息的头指针
cliMesg *create_count()
{
    cliMesg *p1;
    p1=(cliMesg *)malloc(SIZE);
    if(p1==NULL)
    {
        printf("create error\n");
        return NULL;
    }
    p1->next=NULL;

    //记录账户
    FILE *fp;
    fp=fopen("counterMsg","a+");       //打开文件
    if(fp==NULL)
    {
        printf("open error\n");
        return NULL;
    }

    //文件为空
    if(fgetc(fp)==EOF)
    {
        fclose(fp);
        return p1;
    }

    //文件有内容
    rewind(fp);          //文件指针重返文件头

    //获取账号数量
    int counter_num;
    fread(&counter_num,sizeof(int),1,fp);
    printf("counter_num=%d\n",counter_num);
    count=counter_num;

    //建立好友链表
    cliMesg t;
    cliMesg *tmp,*p;
    int i;
    for(i=0;i<counter_num;i++)
    {
        fread(&t,sizeof(cliMesg),1,fp);
        p=p1;
        while(p->next)
        {
            p=p->next;
        }
        tmp=(cliMesg *)malloc(sizeof(cliMesg));
        tmp->next=NULL;
        strcpy(tmp->id,t.id);
        strcpy(tmp->name,t.name);
        strcpy(tmp->passwd,t.passwd);
        tmp->admin=t.admin;
        tmp->hys=t.hys;
        tmp->ed_time=t.ed_time;
        //有好友将数据存入好友链表
        int j;
        for(j=0;j<tmp->hys;j++)
        {
            strcpy(tmp->hy[j],t.hy[j]);
        }

        tmp->fd= -5;  //初始未登录
        tmp->chatroom=0; //初始未私聊
        tmp->online=0;  //初始未在线
        //tmp->admin=0;  //初始为普通用户
        p->next=tmp;

    }

    fclose(fp);
    return p1;

}

//创建未查看信息的头指针
friMesg *create_buffmsg()
{
    friMesg *x;
    x=(friMesg *)malloc(sizeof(friMesg));
    if(x==NULL)
    {
        printf("create error\n");
        return NULL;
    }
    x->next=NULL;

    FILE *fp;
    fp=fopen("buffMsg","a+");
    if(fp==NULL)
    {
        printf("open error\n");
        return NULL;
    }

    //如果为空文件关闭文件直接返回头指针
    if(fgetc(fp)==EOF)
    {
        fclose(fp);
        return x;
    }

    rewind(fp);

    int n;
    fread(&n,sizeof(int),1,fp);
    printf("urev_num=%d\n",n);
    urev_count=n;

    friMesg t;
    friMesg *p,*p1;
    //创建未查看信息链表
    int i;
    for(i=0;i<n;i++)
    {
        fread(&t,sizeof(friMesg),1,fp);
        p1=x;
        while(p1->next)
        {
            p1=p1->next;
        }
        p=(friMesg *)malloc(sizeof(friMesg));
        p->next=NULL;
        strcpy(p->rid,t.rid);
        strcpy(p->sid,t.sid);
        p->type=t.type;
        strcpy(p->mesg,t.mesg);
        p1->next=p;
    }
    fclose(fp);
    return x;
}

//获取系统时间
char **get_time()
{
    char **str=(char **)malloc(NUM*sizeof(char *));
    time_t t;
    struct tm * lt;
    time (&t);//获取Unix时间戳。
    lt = localtime (&t);//转为时间结构。
    sprintf ( str,"%04d/%02d/%02d %02d:%02d:%02d\n",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);//输出结果
    return str;
}

//保存账户信息
void saveclient()
{
    FILE *fp;
    fp=fopen("counterMsg","w");       //打开文件
    if(fp==NULL)
    {
        printf("open error\n");
        return;
    }
    printf("账户个数=%d",count);
    fwrite(&count,sizeof(int),1,fp);		//先保存账号个数

    cliMesg* p;
    p=head;
    if(p->next==NULL) 		//如果账号列表为空 ,  关闭文件并退出函数
    {
        fclose(fp);
        return ;
    }

    p=p->next;
    //按结构体大小保存账号信息
    while(p)
    {
        fwrite(p,sizeof(cliMesg),1,fp);
        p=p->next;
    }
    printf("账号信息保存成功\n");

    fclose(fp);

}

//保存未查看的消息
void savefile()
{
    FILE  *fp;
    fp=fopen("buffMsg","w");
    if(fp==NULL)
    {
        printf("open error\n");
        return;
    }
    printf("未查看信息个数=%d\n",urev_count);
    fwrite(&urev_count,sizeof(int),1,fp);

    friMesg *p;
    p=head1;
    if(p->next==NULL)
    {
        fclose(fp);
        return;
    }

    p=p->next;
    while(p)
    {
        fwrite(p,sizeof(cliMesg),1,fp);
        p=p->next;
    }
    printf("信息保存成功");
    fclose(fp);

}

//服务器上当前客户端id.txt保存聊天记录
void savefile2(char str[1024],char id[20])
{
    FILE *fp;
    char ch[1024];
    sprintf(ch,"./%s/%s.txt",id,id);
    fp=fopen(ch,"a+");
    if(fp==NULL)			//打开错误关闭程序
        return ;
    memset(ch,0,1024);
    strcat(str,"\n");      //txt文档每行句末尾加特殊换行符
    strcpy(ch,str);
    fwrite(ch,strlen(ch),1,fp);
    printf("聊天记录保存成功\n");
    fclose(fp);
}

//帐号合格性检查
int isnum1(char s[20])
{
    int i=0;
    while(s[i])
    {
        if(!isdigit(s[i]))
        {
            return 0;
        }
        i++;
    }
    if(i<11)
    {
        return 0;
    }
    return 1;
}

//用户注册
void add(int fd)
{
    cliMesg *p1,*p,*p2;

    int leap=0;                                    //标识符,账号是否能正确注册
    p=(cliMesg *)malloc(SIZE);			
    if(p==NULL)
        return;
    char str[256];
    char str1[256];
    memset(str,0,sizeof(str));
    memset(str1,0,sizeof(str1));
    strcpy(str,"请输入您要注册的手机号");
    send(fd,str,strlen(str),0);
    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(str1,str);
    if(!isnum1(str))                 //判断是否纯数字账号
    {
        memset(str,0,sizeof(str));
        strcpy(str,"请输入正确的手机号\n");
        send(fd,str,strlen(str),0);
        return;
    }
    p1=head;
    //判断注册账户是否存在
    while(p1->next)
    {
        if(strcmp(p1->next->id,str)==0)
        {
            leap=1;
            break;
        }
        p1=p1->next;
    }
    if(leap==1)
    {
        memset(str,0,sizeof(str));
        strcpy(str,"账号重复\n");
        send(fd,str,strlen(str),0);
        return;
    }
    //正常注册
    strcpy(p->id,str1);
    memset(str,0,sizeof(str));
    strcpy(str,"请输入密码");
    send(fd,str,strlen(str),0);

    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(p->passwd,str);

    memset(str,0,sizeof(str));
    strcpy(str,"请输入昵称");
    send(fd,str,strlen(str),0);

    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(p->name,str);
    p1=head;
    while(p1->next)
    {
        p1=p1->next;
    }
    p1->next=p;
    p->hys=0;
    p->online=0;
    p->fd=-5;
    p->next=NULL;
    memset(str,0,sizeof(str));
    strcpy(str,"注册成功,您可以登录了\n");
    send(fd,str,strlen(str),0);
    count++;                                 //全局变量账号数量+1
    //保存账户信息
    saveclient();
    memset(str,0,sizeof(str));
    sprintf(str,"mkdir ./%s",p->id);
    system(str);

}

//账户匹配检查
int check_iscount(char id[20])
{
    cliMesg *p;
    if(head->next==NULL)
    {
        return 0;
    }
    p=head->next;
    while(p)
    {
	if(strcmp(id,p->id)==0)
	{
            return 1;
	}
        p=p->next;
    }
    return 0;
}

//密码匹配检查
int check_countpasswd(char id[20],char passwd[20])
{
    cliMesg *p;
    if(head->next==NULL)
    {
        return 0;
    }
    p=head->next;

    while(p)
    {

        if(strcmp(id,p->id)==0 && strcmp(passwd,p->passwd)==0)
        {
            return 1;
        }
        p=p->next;
    }
    return 0;
}

//判断是否在线
int countOnline(char id[20])
{
    cliMesg *p;
    p=head;
    while(p)
    {
        if((strcmp(p->id,id)==0) && p->online==1)
        {
            return 1;
        }
        p=p->next;
    }
    return 0;
}

//好友列表
void list_friends(int fd,char id[20])
{
    char sendbuf[1024]={0};
    cliMesg *p,*p1;
    int cnt=0;
    p=head;
    p=p->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    int num=p->hys;
    if(num==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"好友列表为空");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"***************好友列表***************");
    send(fd,sendbuf,strlen(sendbuf),0);
    int i;
    for(i=0;i<num;i++)
    {
        p1=head->next;
        char str[20]={0};
        while(p1)
        {
            if(strcmp(p1->id,p->hy[i])==0)
            {
                strcpy(str,p1->name);
                break;
            }
            p1=p1->next;
        }
        memset(sendbuf,0,sizeof(sendbuf));
        if(p1->online==1)
            cnt++;
        sprintf(sendbuf,"%d 好友账号[%s],昵称[%s],[%d]\n",i+1,p->hy[i],str,p1->online);
        send(fd,sendbuf,strlen(sendbuf),0);
    }
    memset(sendbuf,0,sizeof(sendbuf));
    sprintf(sendbuf,"在线好友个数=%d\n",cnt);
    send(fd,sendbuf,strlen(sendbuf),0);
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"**************************************");
    send(fd,sendbuf,strlen(sendbuf),0);

}

//查找已加好友
void find_friends(int fd,char id[20])
{
    cliMesg *p,*p1;
    p=head;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    char find_id[1024]={0};

    strcpy(sendbuf,"请输入您要查找的手机号");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,find_id,sizeof(find_id),0);
    //查找手机号是否存在
    if(check_iscount(find_id)==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"此号码不存在");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    //查找自己是否有该好友
    p=p->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    if(p->hys==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"没有此好友");
        send(fd,sendbuf,strlen(sendbuf),0);
    }
    int i;
    int num=p->hys;
    for(i=0;i<num;i++)
    {
        //如果找到
        if(strcmp(p->hy[i],find_id)==0)
        {
            //将其昵称取出
            p1=head->next;
            char str[20]={0};
            while(p1)
            {
                if(strcmp(p1->id,find_id)==0)
                {
                    strcpy(str,p1->name);
                    break;
                }
                p1=p1->next;
            }
            memset(sendbuf,0,sizeof(sendbuf));
            sprintf(sendbuf,"该好友账户为%s,昵称为%s",find_id,str);	
            send(fd,sendbuf,strlen(sendbuf),0);			
        }

    }
}

//删除好友
void del_friends(int fd,char id[20])
{
    cliMesg *p,*p1;
    int i,leap=0;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};

    p=head->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    if(p->hys==0)
    {
        strcpy(sendbuf,"您的好友列表为空");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    //好友列表含有信
  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Ubuntu系统下进行socket编程,需要使用C语言中的socket编程接口。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> int main() { int socket_desc, client_sock, c, read_size; struct sockaddr_in server, client; char client_message[2000]; // 创建socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Could not create socket"); } // 绑定IP地址和端口号 server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(8888); if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { printf("bind failed"); return 1; } printf("bind done"); // 监听连接 listen(socket_desc, 3); // 等待连接 printf("Waiting for incoming connections...\n"); c = sizeof(struct sockaddr_in); client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c); if (client_sock < 0) { printf("accept failed"); return 1; } printf("Connection accepted"); // 接收客户端消息并回复 while ((read_size = recv(client_sock, client_message, 2000, 0)) > 0) { printf("Received message: %s\n", client_message); write(client_sock, client_message, strlen(client_message)); memset(client_message, 0, 2000); } if (read_size == 0) { printf("Client disconnected"); } else if (read_size == -1) { printf("recv failed"); } return 0; } ``` 这是一个简单的TCP服务器示例代码,它监听本地IP地址的8888端口,等待客户端连接请求。当客户端连接成功后,服务器会接收客户端发送的消息,并回复同样的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值