基于Linux c 用socket和线程 实现的简易聊天室之服务器

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sqlite3.h>


#define PORTNUMBER 9994
#define MAXNUM 10
#define OK 1
#define ERROR 0




typedef  int Elementtype; 
typedef  int Status; 


//与客户端一致的结构体
typedef struct client
{
Elementtype id;
Elementtype flag;
Elementtype case_num;//服务器进行功能选择 
Elementtype case_numnext;//登录成功聊天功能选择
char name[100];
    char password[150];
//char content_c[1024];//接收客户端发送消息

}Client_message;


//定义一个服务器的结构体
typedef struct server
{   
    Elementtype i_s; 
    Elementtype num_s[10];

Elementtype case_snum;//服务器发送进行的功能  0注册成功,1登录失败,2普通用户登录,3管理员登录
Elementtype id__s;    //4私聊时查找ID有人,5私聊查找ID没人,6查询在线人数
  char name_s[100];
    char password_s[150];
//char content_s[1024];//服务器发送的消息缓存区

}Server_message;
//链表结构体
typedef struct node
{
int id_l;
int fd_l;
struct node *next;
}linkedlist;




Client_message msg_accept;//定义一个全局的结构体名字,接收客户端的结构体
Server_message msg_send;//定义一个全局的结构体名字,发送服务器的结构体




linkedlist *list;
//链表函数
linkedlist *createlinkedlist();
int getcount(linkedlist *list);
//void insert1(linkedlist *list, int id, int fd);
linkedlist *insert2(linkedlist *list, int id, int fd);
int queryfd(linkedlist *list, int id);
int queryid(linkedlist *list, int fd);
void printf_list(linkedlist *list);
linkedlist *dellinkedlist(linkedlist *list, int fd);


void *func(void * arg);


int newfd;//定义一个全局整形的套接字


int main(int argc, char *argv[])
{
    system("clear");

//message msg_accept;
int ret;

printf("服务器正在初始化......\n");
sleep(2);

int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == socket_fd)
{
perror("建立通信失败");
exit(1);
}

struct sockaddr_in server_addr;

memset(&server_addr, 0, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORTNUMBER);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

printf("初始化服务器成功......\n");
printf("正在启动服务器......\n");
    sleep(2);

if (-1 == bind(socket_fd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)))
{
perror("绑定地址失败");
exit(2);
}

if(-1 == listen(socket_fd, MAXNUM))//最大监听用户人数为10
{
perror("监听失败");
exit(3);
}

printf("服务器启动成功......\n");


sqlite3 *db;
ret = sqlite3_open("./server.db", &db);//打开数据库
if(ret != SQLITE_OK)
{
printf("打开数据库失败\n");
}

printf("打开数据库成功......\n");
printf("正在等待客户端的连接......\n");

ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
   printf("关闭数据库失败\n");
}

//创建一个单链表
list = createlinkedlist();
pthread_t pid;

while(1)
{
struct sockaddr_in client_addr;
int length = sizeof(struct sockaddr);

newfd = accept(socket_fd, (struct sockaddr *)(&client_addr), &length);
if (-1 == newfd)
{
perror("接收失败");
exit(1);
}
printf("客服端%d连上了服务器......\n",newfd);

pthread_create(&pid,NULL,(void*)func,(void*)newfd);

    }

//close(newfd);
return 0;
}




void *func(void * arg)
{
    int newfd = (int)arg;//强转为套接字类型
    char sendbuff[1024] = {0};//服务器发送信息
    char buff[1024] = {0};//把套接字先缓存到的区域
int ret;
static int num = 1000;//用作ID

// message *msg_accept = (message *)arg ;//把arg强转为结构体

while(1)
{

   ret = read(newfd, buff,1024);
if(-1 == ret)
{
            perror("读取错误");
            exit(1);
}  

memset(&msg_accept,0,sizeof(msg_accept));//清空结构体
   memcpy(&msg_accept,buff,sizeof(msg_accept));//把收到的信息转换为结构体

//printf("msg_accept.name = %s\t,msg_accept.password = %s\n",msg_accept.name,msg_accept.password);
//printf("msg_accept.case_num = %d\n",msg_accept.case_num);
switch(msg_accept.case_num)
{
case 1 : //客户请求注册
       {

printf("---------------------------------------------\n");
printf("客户端需要注册的名字为:  %s    密码 :%s\n",msg_accept.name,msg_accept.password);
printf("---------------------------------------------\n");      
 
sqlite3 *db;
char *errmsg;
ret = sqlite3_open("server.db",&db);
if(ret != SQLITE_OK)
{
perror("打开数据库失败");
exit(2);
}

char sql_insert[1024] = {0};

sprintf(sql_insert,"insert into server(id ,name,password) values(%d,'%s','%s');",num,msg_accept.name,msg_accept.password);
printf("----------------------以下信息已进入数据库-----------------------\n");
printf("%s\n",sql_insert);
printf("-----------------------------------------------------------------\n");
ret = sqlite3_exec(db,sql_insert,NULL,NULL,&errmsg);

if(ret != SQLITE_OK)
{
perror("插入数据库失败");
exit(3);
}
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
perror("关闭数据库失败");
exit(4);
       }

           msg_send.case_snum = 0;
msg_send.id__s = num;

num++;

memset(sendbuff,0,1024);
memcpy(sendbuff,&msg_send,sizeof(msg_send));

ret = write(newfd ,sendbuff, 1024);
                if(-1 == ret)
                {
                    perror("写入失败");
                    exit(2);
                } <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值