1. 程式人生 > >C,WEB實現登陸註冊功能

C,WEB實現登陸註冊功能

本文是一遍入門部落格,內容以web製作前端頁面,以C語言作為後臺語言,以mysql資料庫儲存資料實現基本的登陸註冊功能,伺服器為centos 7系統

積分有多的小夥伴可以前往C語言後臺程式碼直接下載完整原始碼支援一下原創,謝謝。

1.安裝並登入mysql資料庫

2.建立test資料庫:create database test;

3.新增userinfo表:create table userinfo(name char(16) not null,password char(32) not null,PRIMARY KEY (name) );

4.退出資料庫

5.找到mysql/include和mysql/lib目錄所在路徑

6.新建檔名改為index.html並將下列程式碼複製貼上進去並將第34行的127.0.0.1修改為你的伺服器地址 

<!DOCTYPE html>
<head>
<script type="text/javascript">
var type;
function login(){
	type="login";
	send();
}

function register(){
	type="register";
	send();
}

function send()
{
	var x = document.forms["myform"]["fname"].value;
	var y = document.forms["myform"]["fpass"].value;
	var text = {name:x,password:y,type:type};
	var xmlhttp;
	
	if (x == "" || x == null) {
        alert("使用者名稱和密碼不能為空");
		return false;
    }else if (y == "" || y == null){
		alert("使用者名稱和密碼不能為空");
		return false;
	}
	if (window.XMLHttpRequest){
		xmlhttp=new XMLHttpRequest();
	}else{
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	xmlhttp.open("post","http://127.0.0.1:8000/",true);
	xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	xmlhttp.send(JSON.stringify(text));
	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
		}
	}	
}
</script>
</head>
<body>
<h1>登陸</h1>
<form name="myform">
名字:<input type="text" name="fname" required="required"><br/><br/>
密碼:<input type="password" name="fpass" required="required"><br/><br/>
<button type="button" onclick="login()">登陸</button>
<button type="button" onclick="register()">註冊</button>
<br />
</form>
<div id="myDiv"></div>
</body>
</html>

7.新建main.c檔案並將下列程式碼複製貼上上去,並將第114行的password修改為你的資料庫密碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include "cJSON.h"
#include <mysql.h>

#define MAX_EVENTS           	1024	//最大連線數 
#define REQUEST_LEN_MAX			1024    //緩衝區大小
#define DEFEULT_SERVER_PORT     8000	//程式預設使用埠(可更改)

int main(int argc, char *argv[])
{
	int 				res;
	int                 conn_fd;					//要讀取的socket檔案描述符
	int                 listen_fd;  				//服務端套接字
	int                 port = DEFEULT_SERVER_PORT;	//初始化預設埠為8000
    char                str[INET_ADDRSTRLEN];		//儲存客戶端IP
    struct sockaddr_in  servaddr;					//初始化sockaddr_in結構體變數
	struct sockaddr_in  cliaddr;					//初始化sockaddr_in結構體變數
	socklen_t           cliaddr_len;				//儲存客戶端套接字長度
	MYSQL 				*conn_ptr;	
    MYSQL_RES 			*res_ptr;
    MYSQL_ROW 			sqlrow;
	char 				*login="login",*reg="register";	
    char 				sql[1024],Data[1024],Response[1024];
	char				ResponseHead[] = "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin:*\r\n\r\n";
	
    if(argc > 1) 									//argc: 整數,用來統計你執行程式時送給main函式的命令列引數的個數
        port = atoi(argv[1]);						//argv[0]指向程式執行的全路徑名,argv[n]指向在DOS命令列中執行程式名後的第n個字串
    if(port<=0 || port>0xFFFF) {					//判斷使用者輸入埠是否超出(1-65535)範圍(0-1023為保留埠,不建議使用)
        printf("Port(%d) is out of range(1-%d)\n", port, 0xFFFF);
        return -1;
    }

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(listen_fd == -1){							//正常返回0,異常-1
		printf("建立套接字失敗!\n");
        return -1;
    }
	
    memset(&servaddr, 0, sizeof(servaddr)); 		//servaddr每個位元組都用0填充
    servaddr.sin_family = AF_INET;					//使用IPv4地址
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);	//INADDR_ANY,所有網絡卡地址
    servaddr.sin_port = htons(port);				//埠;	
    bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));	//將套接字和IP、埠繫結,正常返回0,異常-1
    listen(listen_fd, 5000);								//監聽套接字,backlog 為請求佇列的最大長度
	cliaddr_len = sizeof(cliaddr);							//cliaddr客戶端套接字長度
	printf("Listen %d\nAccepting connections ...\n",port); 	//列印正在監聽的埠
					  
    int epoll_fd=epoll_create(MAX_EVENTS);					//建立一個epoll控制代碼  	
    if(epoll_fd==-1)  										//判斷控制代碼是否建立成功
    {  
        perror("epoll_create failed\n");  
        exit(EXIT_FAILURE);  
    }  
	
    struct epoll_event ev;									//epoll事件結構體  
    struct epoll_event events[MAX_EVENTS];					//事件監聽佇列  
    ev.events=EPOLLIN|EPOLLET;								//表示對應的檔案描述符可讀(包括對端SOCKET正常關閉)
    ev.data.fd=listen_fd;  									//將listen_fd設定為要讀取的檔案描述符							
      
    if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_fd,&ev)==-1)	//註冊新的listen_fd到epoll_fd中  
    {  
        perror("epll_ctl:servaddr register failed\n");  
        exit(EXIT_FAILURE);  
    }  
    int nfds;												//epoll監聽事件發生的個數 
    while(1)  												//迴圈接受客戶端請求
    {  
        nfds=epoll_wait(epoll_fd,events,MAX_EVENTS,-1); 	//等待事件發生 
        if(nfds==-1)  														
        {  
            perror("start epoll_wait failed\n");  
            continue;  										//跳過當次迴圈
        }  
        int i;  
        for(i=0;i<nfds;i++)  
        {  
            if(events[i].data.fd==listen_fd)				//客戶端有新的連線請求    
            {      
                if((conn_fd=accept(listen_fd, (struct sockaddr *)&cliaddr, &cliaddr_len))<0)  
                {     
                    perror("accept conn_fd failed\n");     
                    exit(EXIT_FAILURE); //退出當前程式
                }  
                ev.events=EPOLLIN;		//表示對應的檔案描述符可讀(包括對端SOCKET正常關閉)
				ev.data.fd=conn_fd;  	//將conn_fd設定為要讀取的檔案描述符  
                if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,conn_fd,&ev)==-1){  
                    perror("epoll_ctl:conn_fd register failed\n");  
                    exit(EXIT_FAILURE); //退出當前程式
                }  
				char buffer[REQUEST_LEN_MAX];
				memset(buffer, 0, REQUEST_LEN_MAX);		//buf每個位元組都用0填充
				read(conn_fd, buffer, REQUEST_LEN_MAX);	//讀取客戶端傳送資料
			
				char *buff = buffer;	//處理客戶端發來的資料
				while (*buff != '{')
					buff++;
				cJSON *json, *json_name, *json_password, *json_type;
				json = cJSON_Parse(buff); //解析成json形式
				json_name = cJSON_GetObjectItem(json, "name");  //獲取鍵值內容
				json_password = cJSON_GetObjectItem(json, "password");
				json_type = cJSON_GetObjectItem(json, "type");
	
				conn_ptr = mysql_init(NULL);
				if (!conn_ptr) {
					return 0; 
				}
				conn_ptr = mysql_real_connect(conn_ptr, "localhost", "root", "password", "test", 0, NULL, 0);
				if (conn_ptr) {
					if(strcmp(json_type->valuestring, login)==0){		
						sprintf(sql, "select password from userinfo where name='%s' and password='%s'", json_name->valuestring, json_password->valuestring);
						res = mysql_query(conn_ptr, sql); //查詢語句
						if (res) {
							printf("SELECT error:%s\n",mysql_error(conn_ptr));
						} else {
							res_ptr = mysql_store_result(conn_ptr);             //取出結果集
							if(res_ptr) {
								if(sqlrow = mysql_fetch_row(res_ptr)){
									sprintf(Data, "%s login success\n",json_name->valuestring);
								}else{
									sprintf(Data, "user name or password error,please re-enter\n");
								}
							}
							mysql_free_result(res_ptr);	
						}
					}else if (strcmp(json_type->valuestring, reg)==0){
						sprintf(sql, "select password from userinfo where name='%s'", json_name->valuestring);
						res = mysql_query(conn_ptr, sql); //查詢語句
						if(res){
							printf("SELECT error:%s\n",mysql_error(conn_ptr));
						}else{
							res_ptr = mysql_store_result(conn_ptr);             //取出結果集
							if(res_ptr){
								if(sqlrow = mysql_fetch_row(res_ptr)){
									sprintf(Data,"%s is used,Please change your name\n", json_name->valuestring);
								}else{
									sprintf(sql, "insert into userinfo(name,password) values('%s','%s')", json_name->valuestring, json_password->valuestring);
									res = mysql_query(conn_ptr, sql);   //可以把insert語句替換成delete或者update語句,都一樣的    
									if(!res){ 
										sprintf(Data, "%s register success\n",json_name->valuestring);
									}else{       //打印出錯誤程式碼及詳細資訊  
										fprintf(stderr, "Insert error %d: %s\n",mysql_errno(conn_ptr),mysql_error(conn_ptr));  
									} 			
								}
							}	
							mysql_free_result(res_ptr);	
						}		
					}
				}else{
					printf("Connection failed\n");
				} 
				strcpy(Response,ResponseHead);
				strcat(Response, Data);
				write(conn_fd, Response, strlen(Response));	//傳送資料回客戶端
				printf("ResponseData:%s\n",Data);
				
				mysql_close(conn_ptr);
				cJSON_Delete(json);			
				close(conn_fd);		//關閉套接字
    	    }
		}
    } 
    return 0;
}	

8.前往cJSON官網下載cJSON,將其中的cJSON.c和cJSON.h複製到main.c所在目錄

9.gcc main.c cJSON.c -o login  -I /usr/include/mysql -L /usr/lib64/mysql -l mysqlclient -lm

//將/usr/include/mysql和/usr/lib64/mysql更改為你係統上對應的mysql include和lib路徑再執行

10.執行成功後會在當前目錄下生成一個名為  mysql  的可執行檔案,執行該檔案我們的服務端就正常啟動了

11.用瀏覽器開啟index.html,然後就可以輸入使用者名稱和密碼開始測試了