版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
..《移動通信與無線網(wǎng)絡》大作業(yè)報告校車訂票系統(tǒng)課程:學校:組長:組員:完成時間:目錄TOC\z\o"1-3"\u\h一需求分析⑺編制設計說明書??傮w設計過程可分為兩個主要階段:<1>功能設計,確定車站售票系統(tǒng)的實現(xiàn)方案;結構設計,確定該軟件的結構。功能設計是在需求分析的基礎上進行的,這里所說的"功能"是泛指的,不僅指問題定義中列出的功能,還包括軟件定義時確定的任何一個獨立的數(shù)據(jù)加工或處理步驟,例如添加、刪除、查詢和各個特定功能的算法實現(xiàn)等。<2>結構設計,是將整個系統(tǒng)按照不同的功能和層次劃分為一個個功能簡單明確且相對獨立的部分〔模塊,每個模塊實現(xiàn)系統(tǒng)的一項具體功能,自頂向下,逐步細化。結構設計是確定程序由哪些模塊組成,以及這些模塊之間的關系。1.1系統(tǒng)功能設計本系統(tǒng)分三個模塊,登錄功能模塊;管理員功能模塊,實現(xiàn)車票和車次管理;普通用戶功能模塊,實現(xiàn)車票和個人信息管理。校車車票網(wǎng)上訂票系統(tǒng)簡單、操作靈活、方便、反應快速、計算準確,系統(tǒng)運行穩(wěn)定、安全可靠,而且有良好的交互界面,讓使用者可以方便、快速地掌握。1.2系統(tǒng)的總體結構根據(jù)系統(tǒng)分析,按照結構化程序設計的要求得到了下面的系統(tǒng)功能模塊圖:刪除車次發(fā)布車次刪除車次發(fā)布車次更新車次管理員功能選擇更新車次管理員功能選擇校車消息推送消息校車消息推送消息天氣信息天氣信息校車票網(wǎng)上訂票系統(tǒng)校車票網(wǎng)上訂票系統(tǒng)修改信息修改信息修改信息修改信息賬戶重置賬戶重置普通用戶功能選擇普通用戶功能選擇查詢信息車次查詢查詢信息車次查詢時間查詢時間查詢車票管理車票管理預訂車票退去車票退去車票圖5校車車票網(wǎng)上訂票系統(tǒng)總體功能圖1.3子模塊描述各個子模塊描述如下:1.登錄功能模塊:打開手機應用程序,進入登錄功能模塊,選擇登錄身份區(qū)別是普通用戶或是系統(tǒng)管理員。2.管理員功能模塊:車次管理功能模塊主要實現(xiàn)車次的添加、車次更新、刪除等功能。同時為了更好的提供出行信息,管理員可以根據(jù)天氣信息推薦學生注意天氣的變化等信息,溫馨地關心學生。3.普通用戶功能模塊:<1>查詢功能模塊:主要完成車票信息查詢、訂票信息查詢等功能。<2>車票管理功能模塊:主要完成校車車票的訂票,退票等功能。<3>個人信息管理功能模塊:主要完成個人信息的修改等功能。四視圖設計1E-R圖2數(shù)據(jù)流圖數(shù)據(jù)流程圖是以圖形的方式表達在問題中信息的變換和傳遞過程。它把系統(tǒng)看成是由數(shù)據(jù)流聯(lián)系的各種概念的組合,用分解及抽象手段來控制需求分析的復雜性,采用分層的數(shù)據(jù)流程圖來表示一個復雜的系統(tǒng)。校車車票網(wǎng)上訂票系統(tǒng)系統(tǒng)登錄數(shù)據(jù)流圖:開始開始登錄登錄身份識別身份識別管理員/普通用戶管理員操作用戶管理員操作用戶結束結束圖6校車車票網(wǎng)上訂票系統(tǒng)登錄管理數(shù)據(jù)流圖校車車票網(wǎng)上訂票系統(tǒng)車票查詢數(shù)據(jù)流圖:普通用戶普通用戶登錄登錄查詢選擇查詢選擇車次信息查詢訂票信息查詢個人信息查詢修改個人信息車次信息查詢訂票信息查詢個人信息查詢修改個人信息結束結束圖7校車車票網(wǎng)上訂票系統(tǒng)查詢管理數(shù)據(jù)流圖校車車票網(wǎng)上訂票系統(tǒng)車次、車票、時間管理數(shù)據(jù)流圖:圖9校車車票網(wǎng)上訂票系統(tǒng)車次、車票管理數(shù)據(jù)流圖3程序描述3.1客戶端程序本套校車車票訂票系統(tǒng)軟件的客戶端應用程序以手機軟件程序編寫,客戶使用手機安裝下載通過互連網(wǎng)絡對數(shù)據(jù)庫進行訪問,并完成客戶端可以完成的功能。3.2服務器端程序本套校車車票訂票系統(tǒng)軟件的服務器端應用程序,在linux平臺下編寫前臺控制軟件,用電腦主機充當服務器,管理員通過使用該軟件來進行對數(shù)據(jù)庫中的數(shù)據(jù)進行管理。3.3后臺數(shù)據(jù)庫本套校車車票訂票系統(tǒng)軟件的后臺數(shù)據(jù)庫使用MySQL來搭建后臺數(shù)據(jù)庫服務器,用來存放所有的數(shù)據(jù)。4功能描述4.1整體流程設計校車訂票系統(tǒng)管理員登陸用戶登錄用戶注冊前臺瀏覽身份認證身份認證認證失敗認證失敗認證成功認證成功后臺管理模塊用戶前臺模塊圖10整體系統(tǒng)設計思路4.2客戶端的主要功能3.2.1用戶訂票的全部過程用戶登陸成功用戶登陸成功查詢車次查詢余票
預定車票
注銷退訂車票用戶中心圖11用戶訂票流程圖圖12訂票邏輯圖圖13歷史訂單查詢及刪除邏輯4.3服務器的主要功能管理員登陸成功管理員登陸成功用戶管理校車管理訂票管理帳號管理日志管理管理員信息用戶信息校車安排表余票信息消息推送訂票信息退票信息學生數(shù)據(jù)庫系統(tǒng)日志注銷圖14管理員程序?qū)崿F(xiàn)流程4.4軟件時序圖設計軟件程序時,時序圖包含如下的四個元素:1>對象,2>生命線,3>消息,4>激活。圖14用戶預訂車票時序圖圖15用戶退票時序圖4.5數(shù)據(jù)庫接口本套校車訂票系統(tǒng)軟件服務器端的程序是使用eclipse來編寫完成,建立eclipse與數(shù)據(jù)庫的連接使用了ADODB的對象來完成,每個模塊中都使用了Recordset、Command、Connection的對象,因此在模塊中對三者的對象進行定義<分別為:rs、cmd、cn>,并且將cn連接數(shù)據(jù)庫的語句寫好并打開連接,在其他的模塊中共同調(diào)用這三個對象來對數(shù)據(jù)庫進行操作。圖16軟件具體實現(xiàn)接口五程序?qū)崿F(xiàn)1.1客戶端通信方式有和Socket兩種。<1>通信:連接使用的是"請求—響應方式",即在請求時建立連接通道,當客戶端向服務器發(fā)送請求后,服務器端才能向客戶端返回數(shù)據(jù)<2>Socket通信:在雙方建立起連接后就可以直接進行數(shù)據(jù)的傳輸,在連接時可實現(xiàn)信息的主動推送,而不需要每次由客戶端想服務器發(fā)送請求圖17TCP通信模型的Socket于是本設計選擇安卓Socket編程方式實現(xiàn):服務器端:首先聲明一個ServerSocket對象并且指定端口號,然后調(diào)用Serversocket的accept<>方法接收客戶端的數(shù)據(jù),accept<>方法在沒有數(shù)據(jù)進行接收的處于堵塞狀態(tài)。一旦接收到數(shù)據(jù),通過inputstream讀取接收的數(shù)據(jù)客戶端:創(chuàng)建一個Socket對象,指定服務器端的ip地址和端口通過inputstream讀取數(shù)據(jù),獲取服務器發(fā)出的數(shù)據(jù)最后將要發(fā)送的數(shù)據(jù)寫入到outputstream即可進行TCP協(xié)議的socket數(shù)據(jù)傳輸。天氣預報的實現(xiàn)部分,通過資料查詢,我們發(fā)現(xiàn)有如下免費天氣預報獲取途徑,如下所示:Google的天氣預報API中央氣象臺中國氣象局WeatherWebService其中WebXml
天氣預報Web服務,數(shù)據(jù)每2.5小時左右自動更新一次,準確可靠。包括340多個中國主要城市和60多個國外主要城市三日內(nèi)的天氣預報數(shù)據(jù)。于是我們選擇這一資源進行天氣信息的推送。1.2服務器在服務器上的程序由于要接受多個用戶的請求,程序的靈活性和健壯性必須要得到保證,于是本設計采用多線程程序設計思想,對校車系統(tǒng)進行了一些測試。多線程程序有如下優(yōu)點:1>線程間方便的通信機制2>提高應用程序響應3>使多CPU系統(tǒng)更加有效4>改善程序結構設計思路:多線程的程序結構能夠極大的便利程序設計,本設計將整個系統(tǒng)進行功能模塊的分解,使得每個功能模塊獨立不相關,每個模塊占用一個線程,獨立和協(xié)調(diào)地完成整個系統(tǒng)的功能,這種程序設計思路方便管理和增加新的功能,可擴展性強。多線程列表服務器是否可達預售期查詢余票查詢預定車票今日訂單查詢訂單查詢消息詳細信息賬號驗證個人信息查詢密碼修改班車信息查詢退票圖18多線程劃分列表事件監(jiān)聽方面,epoll
是Linux內(nèi)核中的一種可擴展IO事件處理機制,最早在Linux2.5.44內(nèi)核中引入,可被用于代替POSIXselect和poll系統(tǒng)調(diào)用,并且在具有大量應用程序請求時能夠獲得較好的性能,epoll與FreeBSD的kqueue類似,都向用戶空間提供了自己的文件描述符來進行操作。epoll負責監(jiān)聽來自應用程序的TCP/IP請求,并反饋信息到手機應用端1.3加密與解密在與服務器之間的數(shù)據(jù)交互中,除了可以使用post請求來進行加密請求之外,我們可以使用常見的加密算法,對數(shù)據(jù)進行加密。本設計采用DES加密算法。DES<DataEncryptionStandard>,即數(shù)據(jù)加密標準,是一種使用密鑰加密的塊算法,DES算法的入口參數(shù)有三個:Key、Data、Mode。其中Key為7個字節(jié)的工作密鑰;Data是要被加密或被解密的8個字節(jié)數(shù)據(jù);Mode為DES的工作方式,分為:加密或解密。DES是一種對稱的加密算法,加密和解密使用同一個密鑰。本設計使用DES算法進行加密,采用的是CBC模式,填充方式采用PKCS5Padding。
CBC模式指的是加密塊鏈模式,算法加入了初始向量。下面的代碼就是獲取一個初始向量,這種模式的特點是:
1>加密的密文長度為8個字節(jié);2>當明文使用相同的密鑰和初始向量的時候,CBC模式總是產(chǎn)生相同的密文;3>密文塊不能再次排列;4>為避免相同的明文產(chǎn)生相同的密文,可以使用不同的初始化向量;5>一個錯誤發(fā)生以后,當前和以后的密文都會被影響。
在不同的平臺上,只要能保證這幾個參數(shù)的一致,就可以實現(xiàn)加密和解密的一致性:加密和解密的密鑰一致;采用CBC模式的時候,要保證初始向量一致;采用相同的填充模式。六總結在現(xiàn)今移動互聯(lián)網(wǎng)浪潮下,校車訂票系統(tǒng)作為一個典型的應用,正在便利我們的生活,人們的生活越來越離不開手機,人們的大部分活動,交友,娛樂也越來越多依賴手機。關于手機APP的設計和用戶需求分析,也給我們小組所有成員帶來了許多思考。小組設計的初衷在于解決生活中的一些力所能及的事情,或許這些設計不算很完美,卻鍛煉了我們發(fā)現(xiàn)問題,解決問題,提出問題的能力,讓我們在未來的科研路上,可以腳踏實地,少走彎路。本設計將校車訂票系統(tǒng)分三部分進行,手機客戶端,服務器端,數(shù)據(jù)庫。手機客戶端界面設計美觀,操作簡單方便;服務器端在筆記本電腦上,運行在Linux操作系統(tǒng)下,采用多線程框架編寫程序,方便程序管理與更新。校車訂票系統(tǒng)從功能上實現(xiàn):服務端目前具備發(fā)布以及更新訂票信息,注冊帳號,管理數(shù)據(jù)庫等功能;客戶端上具備訂票信息查詢,余票查詢,注冊帳號,天氣信息獲取,預訂車票以及退訂車票等功能。 不過本設計還存在許多不足的地方,表現(xiàn)在如下二個方面:1>進度上:由于沒有獲取國科大學生的基本信息以及校車的真實信息,校車訂票系統(tǒng)還未整體測試和完善。此外穩(wěn)定性及流暢性各種方面都未獲得驗證。2>設計上:校車訂票系統(tǒng)設計思路傳統(tǒng),創(chuàng)新上存在不足。附錄服務器程序1.1數(shù)據(jù)庫功能實現(xiàn)#include"btbs.h"#include<stdlib.h>#include<string.h>#include<stdio.h>#include<unistd.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<pthread.h>staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;void*book_ticket<void*arg>{ if<arg==NULL> { returnNULL; } arg_attrarg_=*<arg_attr*>arg; MYSQLmy_connection; my_connection=*<arg_.my_connection>; intclient_fd=arg_.client_fd; intcmd[1024]={0}; charstudentId[20]={0}; charstartplace[50]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; charweekend[3]={0}; strcpy<cmd,arg_.cmd>; strcpy<studentId,arg_.op_cmd[0]>; strcpy<startplace,arg_.op_cmd[1]>; strcpy<year,arg_.op_cmd[2]>; strcpy<month,arg_.op_cmd[3]>; strcpy<day,arg_.op_cmd[4]>; strcpy<weekend,arg_.op_cmd[5]>; intretval; //mysql_query<arg_.my_connection,"setnames'utf8'">; retval=mysql_query<&my_connection,cmd>; printf<"%s\n",cmd>; if<!retval> { MYSQL_RES*res_ptr=mysql_use_result<&my_connection>; if<res_ptr> { MYSQL_ROWsqlrow=mysql_fetch_row<res_ptr>; if<sqlrow> { if<send<client_fd,"existed",sizeof<"existed">,0>==-1> { fprintf<stderr,"sendinbook_ticketfailed%s\n",strerror<errno>>; } } else { charcmd1[1024]={0}; charcmd2[1024]={0}; if<strcmp<startplace,"雁棲湖校區(qū)">==0&&strcmp<weekend,"0">==0> { sprintf<cmd1,"insertintoTicketsReservationvalues<'C1','%s','%s-%s-%s','07:20:00'>",studentId,year,month,day>; sprintf<cmd2,"updateTicketsLeftsetticketsno=ticketsno-1whereticketsno>0andbusno='C1'andbusdate='%s-%s-%s'",year,month,day>; } elseif<strcmp<startplace,"雁棲湖校區(qū)">==0&&strcmp<weekend,"1">==0> { sprintf<cmd1,"insertintoTicketsReservationvalues<'E1','%s','%s-%s-%s','07:20:00'>",studentId,year,month,day>; sprintf<cmd2,"updateTicketsLeftsetticketsno=ticketsno-1whereticketsno>0andbusno='E1'andbusdate='%s-%s-%s'",year,month,day>; } elseif<strcmp<startplace,"玉泉路校區(qū)">==0&&strcmp<weekend,"0">==0> { sprintf<cmd1,"insertintoTicketsReservationvalues<'C2','%s','%s-%s-%s','15:00:00'>",studentId,year,month,day>; sprintf<cmd2,"updateTicketsLeftsetticketsno=ticketsno-1whereticketsno>0andbusno='C2'andbusdate='%s-%s-%s'",year,month,day>; } else { sprintf<cmd1,"insertintoTicketsReservationvalues<'E2','%s','%s-%s-%s','18:00:00'>",studentId,year,month,day>; sprintf<cmd2,"updateTicketsLeftsetticketsno=ticketsno-1whereticketsno>0andbusno='E2'andbusdate='%s-%s-%s'",year,month,day>; } printf<"%s\n",cmd1>; printf<"%s\n",cmd2>; pthread_mutex_lock<&mutex>; mysql_query<&my_connection,cmd2>; pthread_mutex_unlock<&mutex>; if<mysql_affected_rows<&my_connection>> { mysql_query<&my_connection,cmd1>; if<send<client_fd,"True",sizeof<"True">,0>==-1> { fprintf<stderr,"sendinbook_ticketfailed%s\n",strerror<errno>>; } } else { if<send<client_fd,"False",sizeof<"False">,0>==-1> { fprintf<stderr,"sendinbook_ticketfailed%s\n",strerror<errno>>; } } } mysql_free_result<res_ptr>; } } else { fprintf<stderr,"book_ticketerror%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; } close<client_fd>; returnNULL;}void*drop_ticket<void*arg>{ if<arg==NULL> { returnNULL; } arg_attrarg_=*<arg_attr*>arg; MYSQLmy_connection; my_connection=*<arg_.my_connection>; intclient_fd=arg_.client_fd; intcmd[1024]={0}; charstudentId[20]={0}; charstartplace[50]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; charweekend[3]={0}; strcpy<cmd,arg_.cmd>; strcpy<studentId,arg_.op_cmd[0]>; strcpy<startplace,arg_.op_cmd[1]>; strcpy<year,arg_.op_cmd[2]>; strcpy<month,arg_.op_cmd[3]>; strcpy<day,arg_.op_cmd[4]>; strcpy<weekend,arg_.op_cmd[5]>; intretval=mysql_query<&my_connection,cmd>; if<!retval> { if<mysql_affected_rows<&my_connection>> { charcmd[1024]={0}; sprintf<cmd,"updateTicketsLeftsetticketsno=ticketsno+1wherebusno=<selectbusnofromSchoolBuswherestartplace='%s'andweekend='%s'>andbusdate='%s-%s-%s'",startplace,weekend,year,month,day>; mysql_query<&my_connection,cmd>; if<mysql_affected_rows<&my_connection>> { if<send<client_fd,"True",sizeof<"True">,0>==-1> { fprintf<stderr,"sendindrop_ticketfailed%s\n",strerror<errno>>; } } else { printf<"updateindrop_ticketfailed\n">; } } } close<client_fd>; returnNULL;}void*check_account<void*arg>{ if<arg==NULL> { returnNULL; } arg_attrarg_=*<arg_attr*>arg; MYSQLmy_connection; my_connection=*<arg_.my_connection>; intclient_fd=arg_.client_fd; intcmd[1024]={0}; strcpy<cmd,arg_.cmd>; intretval; //mysql_query<arg_.my_connection,"setnames'utf8'">; retval=mysql_query<&my_connection,cmd>; printf<"%s\n",cmd>; if<!retval> { MYSQL_RES*res_ptr=mysql_use_result<&my_connection>; if<res_ptr> { MYSQL_ROWsqlrow=mysql_fetch_row<res_ptr>; if<sqlrow> { if<send<client_fd,"True",sizeof<"True">,0>==-1> { fprintf<stderr,"sendincheck_accountfailed%s\n",strerror<errno>>; } } else { if<send<client_fd,"False",sizeof<"False">,0>==-1> { fprintf<stderr,"sendincheck_accountfailed%s\n",strerror<errno>>; } } mysql_free_result<res_ptr>; } } else { fprintf<stderr,"check_accounterror%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; } close<client_fd>; returnNULL;}void*modify_passwd<void*arg>{ if<arg==NULL> { returnNULL; } arg_attrarg_=*<arg_attr*>arg; MYSQLmy_connection; my_connection=*<arg_.my_connection>; intclient_fd=arg_.client_fd; intcmd[1024]={0}; strcpy<cmd,arg_.cmd>; intretval; //mysql_query<arg_.my_connection,"setnames'utf8'">; retval=mysql_query<&my_connection,cmd>; if<!retval> { if<mysql_affected_rows<&my_connection>> { if<send<client_fd,"True",sizeof<"True">,0>==-1> { fprintf<stderr,"sendinmodify_passwdfailed%s\n",strerror<errno>>; } } else { if<send<client_fd,"FALSE",sizeof<"FALSE">,0>==-1> { fprintf<stderr,"sendinmodify_passwdfailed%s\n",strerror<errno>>; } } } else { fprintf<stderr,"modify_passwderror%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; if<send<client_fd,"FALSE",sizeof<"FALSE">,0>==-1> { fprintf<stderr,"sendinmodify_passwdfailed%s\n",strerror<errno>>; } } close<client_fd>; returnNULL;}void*query<void*arg>{ if<arg==NULL> { returnNULL; } arg_attrarg_=*<arg_attr*>arg; MYSQLmy_connection; my_connection=*<arg_.my_connection>; intclient_fd=arg_.client_fd; intcmd[1024]={0}; strcpy<cmd,arg_.cmd>; //sleep<10>; intretval; //mysql_query<arg_.my_connection,"setnames'utf8'">; retval=mysql_query<&my_connection,cmd>; if<!retval> { MYSQL_RES*res_ptr=mysql_use_result<&my_connection>; if<res_ptr> { MYSQL_ROWsqlrow; charbuf[4*1024]; memset<buf,0,sizeof<buf>>; while<<sqlrow=mysql_fetch_row<res_ptr>>> { unsignedintfield_count=0; while<field_count<mysql_field_count<&my_connection>> { if<!strcat<buf,sqlrow[field_count]>> { returnNULL; } //printf<"%s\n",sqlrow[field_count]>; if<field_count!=mysql_field_count<&my_connection>-1> { if<!strcat<buf,",">> { returnNULL; } } else { if<!strcat<buf,"#">> { returnNULL; } } field_count++; } } if<mysql_errno<&my_connection>> { fprintf<stderr,"retrieveinqueryerror:%s\n",mysql_error<&my_connection>>; } if<strlen<buf>>0> { strcat<buf,"#">; printf<"%s\n",buf>; if<send<client_fd,buf,strlen<buf>,0>==-1> { fprintf<stderr,"sendinqueryfailed%s\n",strerror<errno>>; } } else { printf<"nothing\n">; if<send<client_fd,",",strlen<",">,0>==-1> { fprintf<stderr,"sendinqueryfailed%s\n",strerror<errno>>; } } mysql_free_result<res_ptr>; } } else { fprintf<stderr,"query%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; } close<client_fd>; returnNULL;}1.2自動更XX票#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<fcntl.h>#include<sys/epoll.h>#include<netdb.h>#include<pthread.h>#include<stdarg.h>#include"btbs.h"#defineMAXEVENTS64#defineQUERY_PRE_SALE2//查詢預售期#defineQUERY_TICKETS3//查詢車票#defineBOOK_TICKETS4//訂票#defineQUERY_ORDERS_TODAY5//查詢今日訂單#defineQUERY_ORDERS6//查詢訂單#definePUSH_MESSAGE7//推送消息#defineCHECK_ACCOUNT9//驗證賬戶#defineQUERY_PERSON_INFO10//查詢個人信息#defineMODIFY_PASSWD11//修改密碼#defineQUERY_SCHOOL_BUS12//查詢校車信息#defineDROP_TICKETS13//退票intstr_split<char*str1,...>;intget_first_field<constchar*str>;intmain<intarg,char*args[]>{ if<arg<2> { return-1; } intport=atoi<args[1]>; intst=socket<AF_INET,SOCK_STREAM,0>;//初始化socket structsockaddr_inaddr;//定義一個ip地址結構 memset<&addr,0,sizeof<addr>>; addr.sin_family=AF_INET;//將addr結構的屬性定位位TCP/IP地址 addr.sin_port=htons<port>;//將本地字節(jié)順序轉(zhuǎn)化位網(wǎng)論字節(jié)順序 addr.sin_addr.s_addr=htonl<INADDR_ANY>;//INADDR_ANY代表這個server上所有的地址 //將IP與server程序綁定 if<bind<st,<structsockaddr*>&addr,sizeof<addr>>==-1> { printf<"bindfailed%s\n",strerror<errno>>; returnEXIT_FAILURE; } //設置socket為非阻塞的 intflags,ret; flags=fcntl<st,F_GETFL,0>; if<flags==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } flags|=O_NONBLOCK; ret=fcntl<st,F_SETFL,flags>; if<ret==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } //監(jiān)聽客戶端的連接請求 ret=listen<st,SOMAXCONN>; if<ret==-1> { printf<"listen%s\n",strerror<errno>>; returnEXIT_FAILURE; } //連接數(shù)據(jù)庫 MYSQLmy_connection; mysql_init<&my_connection>; if<mysql_real_connect<&my_connection,"localhost","root","2222","ReservationSystem",0,NULL,0>> { mysql_query<&my_connection,"setnames'utf8'">; printf<"connectionsuccess\n">; } else { fprintf<stderr,"connectionfailed\n">; if<mysql_errno<&my_connection>> { fprintf<stderr,"connectionerror%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; } returnEXIT_FAILURE; } //創(chuàng)建一個epoll對象 intefd=epoll_create1<0>; if<efd==-1> { printf<"epoll_create%s\n",strerror<errno>>; returnEXIT_FAILURE; } //往epoll對象添加時間 structepoll_eventevent; structepoll_event*events; event.data.fd=st; event.events=EPOLLIN|EPOLLET;//讀入,邊緣觸發(fā)方式 ret=epoll_ctl<efd,EPOLL_CTL_ADD,st,&event>; if<ret==-1> { printf<"epoll_ctl%s\n",strerror<errno>>; returnEXIT_FAILURE; } //bufferwhereeventsarereturned events=calloc<MAXEVENTS,sizeof<event>>; //theeventloop while<1> { intn,i; n=epoll_wait<efd,events,MAXEVENTS,-1>;//沒有事件發(fā)生時一直阻塞 for<i=0;i<n;i++> { if<<events[i].events&EPOLLERR>||\ <events[i].events&EPOLLHUP>||\ <!<events[i].events&EPOLLIN>>> { //anerrorhasoccuredonthisfd,orthesocketisreadyfor //reading printf<"epollerror%s\n",strerror<errno>>; close<events[i].data.fd>; continue; } elseif<st==events[i].data.fd> { //wehaveanotificationonthelisteningsocket, //whichmeansoneormoreincomingconnections while<1> { structsockaddrin_addr; socklen_tin_len; intinfd; charhbuf[NI_MAXHOST],sbuf[NI_MAXSERV]; in_len=sizeof<in_addr>; infd=accept<st,&in_addr,&in_len>; if<infd==-1> { if<<errno==EAGAIN>||<errno==EWOULDBLOCK>> { //wehaveprocessedallincomingconnections break; } else { printf<"accept%s\n",strerror<errno>>; break; } } ret=getnameinfo<&in_addr,in_len,hbuf,sizeof<hbuf>,sbuf,sizeof<sbuf>,NI_NUMERICHOST|NI_NUMERICHOST>;//flag參數(shù),以數(shù)字名返回主機地址和服務地 if<ret==0> {printf<"acceptedconnectionondescriptor%d<host=%s,port=%s>\n",infd,hbuf,sbuf>; } //maketheincomingsocketnon-blockingandaddittothelistoffdstomonitor flags=fcntl<infd,F_GETFL,0>; if<flags==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } flags|=O_NONBLOCK; ret=fcntl<infd,F_SETFL,flags>; if<ret==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } event.data.fd=infd; event.events=EPOLLIN|EPOLLET; ret=epoll_ctl<efd,EPOLL_CTL_ADD,infd,&event>; if<ret==-1> { printf<"epoll_ctl%s\n",strerror<errno>>; returnEXIT_FAILURE; } } continue; } else { //wehavedataonthefdwaitingtoberead.readanddisplayit. //wemustreadwhateverdataisavailablecompletely,asweare //runninginedge-triggeredmodeandwon'tgetanotificationagain //forthesamedata intdone=0; while<1> { ssize_tcount; charbuf[512]; memset<buf,0,sizeof<buf>>; count=read<events[i].data.fd,buf,sizeof<buf>>; if<count==-1> { //iferrno==EAGAIN,thatmeanswehavereadalldata. //sogobacktothemainloop if<errno!=EAGAIN> { printf<"read%s\n",strerror<errno>>; done=1; } break; } elseif<count==0> { //endoffile.theremotehasclosedtheconnection done=1; break; } //splitthestringbuftofetchfieldinfomation //forexample,ifbufisstring"10,studentId",thefieldincludes10andstudentId charcmd[1024]; memset<cmd,0,sizeof<cmd>>; intfunc_id=get_first_field<buf>; arg_attrarg; arg.my_connection=&my_connection; arg.client_fd=events[i].data.fd; pthread_tthr; switch<func_id> { caseQUERY_PRE_SALE: { send<events[i].data.fd,"3",sizeof<"3">,0>; break; } caseCHECK_ACCOUNT: { charfid[3]; memset<fid,0,sizeof<fid>>; charstudentId[20]; memset<studentId,0,sizeof<studentId>>; charpasswd[20]; memset<passwd,0,sizeof<passwd>>; intretval=str_split<buf,fid,studentId,passwd>; sprintf<cmd,"select*fromAccountwhereaccountno='%s'andaccountkey='%s'",studentId,passwd>; arg.cmd=cmd; pthread_create<&thr,NULL,check_account,&arg>; break; } caseMODIFY_PASSWD: { charfid[3]; memset<fid,0,sizeof<fid>>; charstudentId[20]; memset<studentId,0,sizeof<studentId>>; charpasswd[20]; memset<passwd,0,sizeof<passwd>>; charnew_passwd[20]; memset<passwd,0,sizeof<passwd>>; intretval=str_split<buf,fid,studentId,passwd,new_passwd>; sprintf<cmd,"updateAccountsetaccountkey='%s'whereaccountno='%s'andaccountkey='%s'",new_passwd,studentId,passwd>; arg.cmd=cmd; pthread_create<&thr,NULL,modify_passwd,&arg>; break; } caseQUERY_PERSON_INFO: { charfid[3]; memset<fid,0,sizeof<fid>>; charstudentId[20]; memset<studentId,0,sizeof<studentId>>; intretval=str_split<buf,fid,studentId>; sprintf<cmd,"select*fromStudentwherestuno='%s'",studentId>; arg.cmd=cmd; pthread_create<&thr,NULL,query,&arg>; break; } caseQUERY_TICKETS: { charfid[3]={0}; charstartpos[50]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; intretval=str_split<buf,fid,startpos,year,month,day>; sprintf<cmd,"selectticketsnofromTicketsLeftwherebusnoin<selectbusnofromSchoolBuswherestartplace='%s'>andbusdate='%s-%s-%s'",startpos,year,month,day>; arg.cmd=cmd; pthread_create<&thr,NULL,query,&arg>; break; } caseQUERY_ORDERS: { charfid[3]={0}; charstudentId[20]={0}; intretval=str_split<buf,fid,studentId>; sprintf<cmd,"selectSchoolBus.startplace,stuno,busdate,bustimefromTicketsReservation,SchoolBuswhereTicketsReservation.busno=SchoolBus.busnoandstuno='%s'orderbybusdateDESC",studentId>; arg.cmd=cmd; pthread_create<&thr,NULL,query,&arg>; break; } caseBOOK_TICKETS: { charfid[3]={0}; charstudentId[20]={0}; charstartplace[50]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; charweekend[3]={0}; intretval=str_split<buf,fid,studentId,startplace,year,month,day,weekend>; arg.op_cmd[0]=studentId; arg.op_cmd[1]=startplace; arg.op_cmd[2]=year; arg.op_cmd[3]=month; arg.op_cmd[4]=day; arg.op_cmd[5]=weekend; sprintf<cmd,"select1fromTicketsReservationwherebusno=<selectbusnofromSchoolBuswherestartplace='%s'andweekend='%s'>andstuno='%s'andbusdate='%s-%s-%s'limit1",startplace,weekend,studentId,year,month,day>; arg.cmd=cmd; pthread_create<&thr,NULL,book_ticket,&arg>; break; } caseQUERY_ORDERS_TODAY: { charfid[3]={0}; charstudentId[20]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; intretval=str_split<buf,fid,studentId,year,month,day>; // sprintf<cmd,"select*fromTicketsReservationwherestuno='%s'andbusdate='%s-%s-%s'",studentId,year,month,day>; sprintf<cmd,"selectSchoolBus.startplace,stuno,busdate,bustimefromTicketsReservation,SchoolBuswhereTicketsReservation.busno=SchoolBus.busnoandstuno='%s'andbusdate='%s-%s-%s'",studentId,year,month,day>; arg.cmd=cmd; pthread_create<&thr,NULL,query,&arg>; break; } caseQUERY_SCHOOL_BUS: { charfid[3]={0}; intretval=str_split<buf,fid>; sprintf<cmd,"select*fromSchoolBus">; arg.cmd=cmd; pthread_create<&thr,NULL,query,&arg>; break; } caseDROP_TICKETS: { charfid[3]={0}; charstudentId[20]={0}; charstartplace[50]={0}; charyear[6]={0}; charmonth[3]={0}; charday[4]={0}; charweekend[3]={0}; intretval=str_split<buf,fid,studentId,startplace,year,month,day,weekend>; arg.op_cmd[0]=studentId; arg.op_cmd[1]=startplace; arg.op_cmd[2]=year; arg.op_cmd[3]=month; arg.op_cmd[4]=day; arg.op_cmd[5]=weekend; sprintf<cmd,"deletefromTicketsReservationwherebusno=<selectbusnofromSchoolBuswherestartplace='%s'andweekend='%s'>andstuno='%s'andbusdate='%s-%s-%s'",startplace,weekend,studentId,year,month,day>; arg.cmd=cmd; pthread_create<&thr,NULL,drop_ticket,&arg>; break; } } } if<done> { printf<"closedconnectionondescriptor%d\n",events[i].data.fd>; //closingthedescriptorwillmakeepollremoveitfromtheset //ofdescriptorswhicharemonitored //close<events[i].data.fd>; } } } } free<events>; close<st>; returnEXIT_SUCCESS;}staticintstr_split<char*str1,...>{ intnum=0; va_listap; constchardelim[]={","}; char*t=NULL; char*p=NULL; va_start<ap,str1>; t=strtok<str1,delim>; while<t!=NULL&&<p=va_arg<ap,char*>>!=NULL> { num++; strcpy<p,t>; t=strtok<NULL,delim>; } va_end<ap>; returnnum;}staticintget_first_field<constchar*str>{ char*p=strchr<str,','>; charid[3]; memset<id,0,sizeof<id>>; strncpy<id,str,p-str>; intretval=atoi<id>; returnretval;}1.3響應客戶端實現(xiàn)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<fcntl.h>#include<sys/epoll.h>#include<netdb.h>#include<pthread.h>#include<stdarg.h>#include"btbs.h"#defineMAXEVENTS64#defineQUERY_PRE_SALE2//查詢預售期#defineQUERY_TICKETS3//查詢車票#defineBOOK_TICKETS4//訂票#defineQUERY_ORDERS_TODAY5//查詢今日訂單#defineQUERY_ORDERS6//查詢訂單#definePUSH_MESSAGE7//推送消息#defineCHECK_ACCOUNT9//驗證賬戶#defineQUERY_PERSON_INFO10//查詢個人信息#defineMODIFY_PASSWD11//修改密碼#defineQUERY_SCHOOL_BUS12//查詢校車信息#defineDROP_TICKETS13//退票intstr_split<char*str1,...>;intget_first_field<constchar*str>;intmain<intarg,char*args[]>{ if<arg<2> { return-1; } intport=atoi<args[1]>; intst=socket<AF_INET,SOCK_STREAM,0>;//初始化socket structsockaddr_inaddr;//定義一個ip地址結構 memset<&addr,0,sizeof<addr>>; addr.sin_family=AF_INET;//將addr結構的屬性定位位TCP/IP地址 addr.sin_port=htons<port>;//將本地字節(jié)順序轉(zhuǎn)化位網(wǎng)論字節(jié)順序 addr.sin_addr.s_addr=htonl<INADDR_ANY>;//INADDR_ANY代表這個server上所有的地址 //將IP與server程序綁定 if<bind<st,<structsockaddr*>&addr,sizeof<addr>>==-1> { printf<"bindfailed%s\n",strerror<errno>>; returnEXIT_FAILURE; } //設置socket為非阻塞的 intflags,ret; flags=fcntl<st,F_GETFL,0>; if<flags==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } flags|=O_NONBLOCK; ret=fcntl<st,F_SETFL,flags>; if<ret==-1> { printf<"fcntl%s\n",strerror<errno>>; returnEXIT_FAILURE; } //監(jiān)聽客戶端的連接請求 ret=listen<st,SOMAXCONN>; if<ret==-1> { printf<"listen%s\n",strerror<errno>>; returnEXIT_FAILURE; } //連接數(shù)據(jù)庫 MYSQLmy_connection; mysql_init<&my_connection>; if<mysql_real_connect<&my_connection,"localhost","root","2222","ReservationSystem",0,NULL,0>> { mysql_query<&my_connection,"setnames'utf8'">; printf<"connectionsuccess\n">; } else { fprintf<stderr,"connectionfailed\n">; if<mysql_errno<&my_connection>> { fprintf<stderr,"connectionerror%d:%s\n",mysql_errno<&my_connection>,mysql_error<&my_connection>>; } returnEXIT_FAILURE; } //創(chuàng)建一個epoll對象 intefd=epoll_create1<0>; if<efd==-1> { printf<"epoll_create%s\n",strerror<errno>>; returnEXIT_FAILURE; } //往epoll對象添加時間 structepoll_eventevent; structepoll_event*events; event.data.fd=st; event.events=EPOLLIN|EPOLLET;//讀入,邊緣觸發(fā)方式 ret=epoll_ctl<efd,EPOLL_CTL_ADD,st,&event>; if<ret==-1> { printf<"epoll_ctl%s\n",strerror<errno>>; returnEXIT_FAILURE; } //bufferwhereeventsarereturned events=calloc<MAXEVENTS,sizeof<event
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《彎道跑》說課稿
- 5年中考3年模擬試卷初中道德與法治九年級下冊02中考道德與法治真題分項精練(二)
- 人工智能的理論原理
- EMS智能造制生產(chǎn)線項目可行性研究報告寫作模板-拿地申報
- (統(tǒng)考版)2023版高考化學一輪復習第九章有機化合物第1講重要的烴化石燃料學生用書
- 電子產(chǎn)品展示運輸協(xié)議
- 人工智能居間合同模板
- 服裝貿(mào)易居間合同格式
- 住宅精裝修材料采購合約
- 主題餐廳裝飾工程合同
- 期中 (試題) -2024-2025學年譯林版(三起)英語四年級上冊
- 2024注冊安全工程師安全生產(chǎn)管理-考前押題卷
- 火災自動報警系統(tǒng)操作流程圖普通主機
- 運動員技術等級稱號申請表
- 6米滿堂腳手架搭設方案
- 南開《數(shù)據(jù)科學導論》20春期末考核答案
- 小學四年級中華優(yōu)秀傳統(tǒng)文化教案小學四年級山東友誼出版社
- 英語主格賓格所有格一覽表
- 《龜兔賽跑》PPT課件.ppt
- 兒科危急值項目及評價報告制度
- 【學案】 Unit 1 Grammar Predicative clauses 學案-人教版(2019)選擇性必修第二冊
評論
0/150
提交評論