本文是一遍入门博客,内容以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,然后就可以输入用户名和密码开始测试了