1、服務器
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 9999 //端口號
#define REG 6000 //表示註冊請求
#define RES_OK 6001 //成功註冊
#define RES_ERR 6002 //註冊失敗
#define LOGIN 6003 //表示登錄請求
#define LOG_OK 6004 //登錄成功
#define LOG_ERR 6005 //登錄失敗
#define SIZE 20 //賬號密碼的最大長度
typedef enum {FALSE,TRUE}BOOL;
// 創建,綁定端口和ip,監聽套接字
int init();
// 通信套接字
int myAccept(int listen_socket);
//工作函數
void *handl_client(void *v);
//註冊
void reg(int cmd,long client_socket);
//登錄
BOOL login(int cmd,long client_socket);
int main()
{
int listen_socket = init();
if(-1 == listen_socket)
return -1;
while(1)
{
long client_socket = myAccept(listen_socket);
if(-1 == client_socket)
{
continue;
printf("dasdasdas\n");
}
//創建線程
pthread_t thread;
pthread_create(&thread,NULL,handl_client,(void *)client_socket);
pthread_detach(thread);
}
close(listen_socket);
return 0;
}
// 創建,綁定端口和ip,監聽套接字
int init()
{
int listen_socket = socket(AF_INET, SOCK_STREAM, 0); //創建
if(-1 == listen_socket)
{
perror("創建套接字失敗");
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; /* Internet地址族 */
addr.sin_port = htons(PORT); /* 端口號 */
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址, 綁定本地的所有ip地址*/
int ret = bind(listen_socket, (const struct sockaddr *)&addr, sizeof(addr)); //綁定
if(-1 == ret)
{
perror("綁定失敗");
return -1;
}
ret = listen(listen_socket, 5); // 監聽套接字
if(-1 == ret)
{
perror("監聽失敗");
return -1;
}
return listen_socket;
}
// 通信套接字
int myAccept(int listen_socket)
{
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
printf("等待用戶連接\n");
int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &len);
if (-1 == client_socket)
{
perror("連接失敗");
return -1;
}
return client_socket;
}
//工作函數,處理客戶端請求
void *handl_client(void *v)
{
long client_socket = (long)v;
while(1)
{
int cmd;
int ret = read(client_socket,&cmd,sizeof(int)); //判斷請求
if(0 == ret)
{
printf("客戶端退出\n");
break;
}
switch(cmd)
{
case REG: //註冊
reg(cmd,client_socket);
break;
case LOGIN:
login(cmd,client_socket);
break;
}
}
}
//註冊模塊
void reg(int cmd,long client_socket)
{
//註冊協議:客戶端--->服務器
struct data
{
char name[SIZE]; //賬號
char passwd[SIZE]; //密碼
}Data;
//註冊協議:服務器--->客戶端
struct _rep
{
int cmd; //對什麼請求反饋
int result; //處理結果
}Rep = {cmd,RES_OK};
sqlite3 *db;
//打開數據庫
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("數據庫打開失敗\n");
Rep.result = RES_ERR;
}
char *errmsg;
//設計數據庫內容id,賬號,密碼
const char *sql = "create table if not exists mydata(name TEXT,passwd TEXT,primary key(name))";
sqlite3_exec(db, sql, NULL, NULL, &errmsg);
//讀取客戶端的數據部分
read(client_socket,&Data,sizeof(struct data));
//不存在,添加進數據庫
char str[100];
int id = 1;
sprintf (str, "insert into mydata values('%s','%s')",Data.name,Data.passwd);
ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
if (ret != SQLITE_OK)
{
sqlite3_free(errmsg);
printf("數據已經存在\n");
Rep.result = RES_ERR;
}
write(client_socket,&Rep,sizeof(struct _rep));
}
//登錄模塊
BOOL login(int cmd,long client_socket)
{
//登錄協議:客戶端--->服務器
struct data
{
char name[SIZE]; //賬號
char passwd[SIZE]; //密碼
}Data;
//登錄協議:服務器--->客戶端
struct _rep
{
int cmd; //對什麼請求反饋
int result; //處理結果
}Rep = {cmd,LOG_ERR};
//打開數據庫
sqlite3 *db;
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("數據庫打開失敗\n");
return FALSE;
}
//讀取客戶端的數據部分
read(client_socket,&Data,sizeof(struct data));
//進行查找
char *errmsg;
const char *sql = "select * from mydata";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查詢失敗: %s\n", errmsg);
sqlite3_free(errmsg);
Rep.result = LOG_ERR;
return;
}
int i;
printf("%d\n",row);
printf("%d\n",column);
for (i = column; i < (row*column+column); i+=column)
{
if(0 == strcmp(value[i],Data.name) && 0 == strcmp(value[i+1],Data.passwd))
{
Rep.result = LOG_OK;
break;
}
}
write(client_socket,&Rep,sizeof(struct _rep));
if(Rep.result == LOG_ERR)
{
printf("賬號或者密碼錯誤\n");
return FALSE;
}
else if(Rep.result == LOG_OK)
{
printf("%s賬號登錄成功\n",Data.name);
return TRUE;
}
}
2、客戶端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#define PORT 9999 //端口號
#define REG 6000 //表示註冊請求
#define RES_OK 6001 //成功註冊
#define RES_ERR 6002 //註冊失敗
#define LOGIN 6003 //表示登錄請求
#define LOG_OK 6004 //登錄成功
#define LOG_ERR 6005 //登錄失敗
#define SIZE 20 //賬號密碼的最大長度
typedef enum {FALSE,TRUE}BOOL;
//功能
void func(int conn_socket);
//註冊
void Reg(int conn_socket);
//主界面
void menu();
//登錄
BOOL Login(int conn_socket);
//在線
void Online(int conn_socket);
//在線界面
void menu_online();
int main()
{
//創建套接字
int conn_socket = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == conn_socket)
{
perror("創建套接字失敗");
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; /* Internet地址族 */
addr.sin_port = htons(PORT); /* 端口號 */
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址, 綁定本地的所有ip地址*/
//連接客戶端
int ret = connect(conn_socket, (const struct sockaddr *)&addr, sizeof(addr));
if(-1 == ret)
{
perror("綁定失敗");
return -1;
}
func(conn_socket);
close(conn_socket);
return 0;
}
//主界面
void menu()
{
printf("1、登錄聊天室\n");
printf("2、註冊新賬號\n");
printf("0、退出\n");
}
//功能選擇
void func(int conn_socket)
{
while(1)
{
system("clear");
menu();
int i;
scanf("%d",&i);
switch(i)
{
case 2:
Reg(conn_socket);
break;
case 1:
int tmp = Login(conn_socket);
if(tmp == TRUE)
Online(conn_socket);
break;
case 0:
printf("程序已經退出\n");
break;
default :
printf("無效指令\n");
break;
}
if(0 == i)
break;
}
}
//註冊
void Reg(int conn_socket)
{
struct data
{
const int cmd;
char name[SIZE]; //賬號
char passwd[SIZE]; //密碼
}Data ={REG};
struct _rep
{
int cmd; //對什麼請求反饋
int result; //處理結果
}Rep;
//向服務器發送請求
printf("請輸入註冊賬戶:");
scanf("%s",Data.name);
printf("請輸入註冊密碼:");
scanf("%s",Data.passwd);
write(conn_socket, &Data, sizeof(struct data));
//接收服務器反饋信息
printf("正在等待賬號註冊\n");
sleep(1);
int ret = read(conn_socket, &Rep, sizeof(Rep));
if (-1 == ret)
{
perror ("read error");
}
if(Rep.cmd == REG && Rep.result == RES_OK)
{
printf("註冊成功\n");
}
else if(Rep.cmd == REG && Rep.result == RES_ERR)
{
printf("賬號已經存在,註冊失敗\n");
}
}
//登錄
BOOL Login(int conn_socket)
{
//登錄協議:客戶端--->服務器
struct data
{
const int cmd;
char name[SIZE]; //賬號
char passwd[SIZE]; //密碼
}Data={LOGIN};
//登錄協議:服務器--->客戶端
struct _rep
{
int cmd; //對什麼請求反饋
int result; //處理結果
}Rep;
printf("請輸入賬號:");
scanf("%s",Data.name);
printf("請輸入密碼:");
scanf("%s",Data.passwd);
//向服務器發送請求
write(conn_socket, &Data, sizeof(struct data));
//接收服務器反饋信息
printf("賬號登錄中....\n");
sleep(1);
int ret = read(conn_socket, &Rep, sizeof(Rep));
if (-1 == ret)
{
perror ("read error");
}
if(Rep.cmd == LOGIN && Rep.result == LOG_OK)
{
system("clear");
printf("登錄成功\n");
sleep(1);
return TRUE;
}
else if(Rep.cmd == LOGIN && Rep.result == LOG_ERR)
{
system("clear");
printf("賬號或密碼錯誤\n");
sleep(1);
return FALSE;
}
}
//在線界面
void menu_online()
{
printf("1、查看在線用戶\n");
printf("2、進入羣聊\n");
printf("3、進入私聊\n");
printf("4、查看聊天記錄\n");
printf("5、更改用戶密碼\n");
printf("6、在線註銷當前用戶\n");
printf("0、退出登錄\n");
}
//在線
void Online(int conn_socket)
{
}