對於linux下c語言的編程,尤爲是網絡編程這部分,仍是有一些莫名的愛好的。學習了一些東西,若是不加以總結和實際操做,每每容易忘了。因此,在此寫個系列的博客,記錄一下,從零開始寫linux下的服務器編程。但願看到這篇日誌的同窗,多提意見,共同窗習。 linux
對於網絡編程,主要是對socket和IO進行操做。爲了實現高效通信,須要一些策略,後面會介紹到。做爲開篇,主要是對socket的基礎操做的講解。 git
socket本質上就是一個int的數字,文件描述符,用於標識主機間端到端的通信。兩端的主機,經過對該socket進行讀寫,完成雙方的通信。 編程
socket須要新建(socket())、綁定(bind()),監聽(listen),接收鏈接(accept()),以及讀寫(read() write(),還有別的IO函數)等。綁定,是將已經新建好的socket與本地的地址進行一個聯繫。地址( struct sockaddr_in )的設定每每根據須要的具體狀況,包括協議、端口、IP地址等。監聽是告訴客戶端,服務器這邊已經準備好了,等待爲其服務啦。接受鏈接是在客戶端請求鏈接時,雙方創建鏈接的通道,爲通信作好準備。接下來,就是數據交換(讀和寫)。關於讀寫的函數,比較多,read()\write(), recv()\send()、recvfrom\sendto(),recvmsg()\sendmsg()等。幾組函數間比較類似,個別又有特色,接下來會有一篇專門介紹各類讀寫函數的。 服務器
學習的過程,更多的仍是在於動手寫。下面先寫一個簡單的demo,一個回射服務器(就是客戶端傳來什麼內容,服務器就寫回給客戶端什麼內容)。接下來的幾個例子,都是在此基礎上進行改進的。固然了,後面隨着深刻,簡單的回射服務器可能不能知足咱們的要求了,咱們會寫個http服務器之類的。下面是代碼。具體的代碼能夠見託管處 http://git.oschina.net/mengqingxi89/codelittle/blob/master/codes/echoserver/echoser.cpp。固然了,這個demo是最基本的demo,只能處理一個客戶的請求,異常處理什麼的也沒考慮。不過,接下來,咱們會慢慢的優化,不要着急哦。 網絡
#include"head.h" /*由於涉及的頭文件比較多,單寫了一個頭文件,包括引用頭文件和全局變量、經常使用函數的定義等*/ int main(int argc, char **argv) { if(argc<3) { printf("usage: %s ip port\n",basename(argv[0])); exit(0); } printf("start echoback server...\n"); char * ip=(char * ) argv[1]; int port =atoi(argv[2]); /*構造服務器端的地址,主要是填充sockaddr_in 結構體*/ struct sockaddr_in server_address; bzero(&server_address,sizeof(server_address)); server_address.sin_family=AF_INET; inet_pton(AF_INET,ip,&server_address.sin_addr); server_address.sin_port=htons(port); int listenfd=socket(AF_INET,SOCK_STREAM,0); assert(listenfd>=0); setnonblock(listenfd); int ret=bind(listenfd,(struct sockaddr *) &server_address, sizeof(server_address)); assert(ret==0); ret=listen(listenfd,5); assert(ret==0); /*服務器服務啓動,等待客戶端的連接的到來*/ int run_flag=1; char buf[1024]; int conn=-1; while(run_flag) { int acfd=accept(listenfd,NULL,NULL); /*由於listenfd是非阻塞的,因此,可能返回是小於0的值,此時應該繼續處理上一個鏈接*/ if(acfd>=0) conn=acfd; printf("%d\n",conn); bzero(buf,1024); int ret=read(conn,buf,1023); if(ret>0) { buf[ret]=0; printf("received: %s\n",buf); write(conn,buf,ret); } else if (ret==0) { printf("read 0\n"); close(conn); } else { printf("read error\n"); close(conn); } } }
在服務器端執行該文件,而後另起一個終端,用telnet鏈接對應的IP和PORT,就能夠實現服務器與客戶端的通信了。 socket