windows下的C++ socket服務器(2)


int make_server_socket(int port);//1
void handleAccept(int socket_fd);//2
int main(int ac, char *av[])
{
    int tcp_socket = make_server_socket(8888);
    if (tcp_socket == -1)
    {
        exit(0);
    }
    thread t;//3
    while (1)
    {
        int socket_fd = accept(tcp_socket, nullptr, nullptr);  //4  
        t = thread(handleAccept, socket_fd);//3
        t.detach();//3
    }
    
    system("pause");
}

1.int make_server_socket(int port) 用於創建服務端的socket的函數,將在后面進行講解。

2.void handleAccept(int socket_fd) 用於處理連接到服務端的客戶端的函數,將在后面進行講解。

3.thread C++11中出現的用於多線程編程,需要#include <thread> ,以前涉及到多線程編程時,在windows中需要使用CreateThread,而在linux中需要用pthread_create函數

而當thread出現后,在代碼層面上,windows和linux就統一了。

thread的構造函數,

template<class _Fn,class... _Args>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)

{

//     

}

簡單來說第一個參數表示函數的名字,其余的參數表示第一個參數所對應函數的參數,模板中的…用到了C++11中的變長模板這一個概念。

比如 t=thread(handleAccept,socket_fd)// handleAccept 函數名字,該函數有一個int的參數,socket_fd對應該int 參數

 

在線程創建完成后,我用t.detach(),將線程與主線程分離開,這樣線程在線程結束時,就會清空自動該線程所占用的棧空間。並且主線程也可以和支線程一起運行,不用等待支線程結束后才能繼續執行。

而如果我們如果使用t.join();會導致主線程必須等待所有當前的支線程結束后才可以往下執行。這樣就無法同時處理不同客戶端的請求了

還有要注意的是thread默認的joinable值是true,這意味着線程是不會析構的,在重復對同一對象創建線程時是會異常終止的,我們需要使用detach()和join(),將joinable的值改為false

 

例如

void print()
{
    string a("hello");
    cout << a << endl;
}
int main(int ac, char *av[])
{
    thread t;
    t = thread(print);
    //t.detach();
    t = thread(print);
    //t.detach();
    
    system("pause");
}

搜狗截圖14年03月04日2213_1

而如果我們把注釋去掉就可以正常運行了,同樣將t.detach()改為t.join()也可以。

 

關於thread的更多資料

http://www.oschina.net/translate/cplusplus-11-threading-make-your-multitasking-life

http://www.cnblogs.com/haippy/p/3236136.html

 

 

4.accept();

accept()函數在windows下

SOCKET accept(SOCKET s,sockaddr* addr,int* addrlen );

accept函數的第一個參數為服務器的socket描述字,第二個參數為指向struct sockaddr *的指針,用於返回客戶端的協議地址,第三個參數為該協議地址的長度。如果accpet成功,那么返回一個socket,代表與返回客戶的TCP連接。

在本程序中

int socket_fd = accept(tcp_socket, nullptr, nullptr);

tcp_socket是我們創建的服務器的socket描述字,而協議地址和該協議地址的長度,我們這里不需要,就設置為nullptr(nullptr為C++11 新增的用於替代null)

 

在這里accept函數是阻塞的,在沒有新連接請求來的情況下,accept一直在這里等,函數沒有返回,程序也不會往下運行。。

 

大家可以發現accept在windows中返回的SOCKET類型,而我們用一個int型接受返回值。

大家可以在vs2013中發現

搜狗截圖14年03月04日2230_2

所以SOCKET和int是可以進行轉換的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM