操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    學(xué)完C語(yǔ)言做不出東西?不存在的,咱們做一個(gè)最“隱私”的聊天器,就倆人,你和我。咱們聊天的信息你知我知沒(méi)別人知。

    我們直接開(kāi)始寫(xiě)代碼,只要你會(huì)基礎(chǔ)的C語(yǔ)言,不要擔(dān)心看不懂,不懂的我?guī)湍闩俑鶈?wèn)底,把根都挖出來(lái)嚼爛,絕對(duì)懂。

    一、一個(gè)聊天軟件的基礎(chǔ)模型是怎么樣的?

    你是個(gè)新手的話你可能就會(huì)問(wèn),什么是模型?!聽(tīng)不懂,我在騙你學(xué)習(xí)。放心,我現(xiàn)在就告訴你什么是基礎(chǔ)“模型”。

    我們可以簡(jiǎn)單的理解“模型”指這個(gè)聊天軟件基本是怎么進(jìn)行通信的,常規(guī)形式是怎樣的,只要清楚了這個(gè)形式流程,然后在這個(gè)流程中添加一些代碼就ok了,啥都不用想。如果你還是不懂什么是“流程”,那我就跟你說(shuō)這個(gè)是一個(gè)步驟,只需要懂這個(gè)步驟,我們使用代碼編寫(xiě)這個(gè)步驟就可以完成了。

    好了,現(xiàn)在沒(méi)啥問(wèn)題了吧?現(xiàn)在開(kāi)始,第一步在一個(gè)通信中,一般有一個(gè)服務(wù)端。那什么是服務(wù)端?

    1.1 什么是服務(wù)端

    服務(wù)端就簡(jiǎn)單了,曾經(jīng)…曾經(jīng)…你去例如移動(dòng)或者聯(lián)通的營(yíng)業(yè)挺,客服小姐姐就會(huì)對(duì)你提供服務(wù),例如業(yè)務(wù)辦理,辦個(gè)卡,銷(xiāo)個(gè)號(hào)等,那我們的服務(wù)端是用來(lái)通信的,所以這個(gè)服務(wù)端就是指等待跟我聊天的人,只要你上線了,開(kāi)電腦打開(kāi)軟件了,連接上我的服務(wù)端了,咱們就可以聊天了。

    服務(wù)端一般就是一直在這里等你上線的那個(gè),風(fēng)里雨里我在這里等你。

    1.2 又不懂什么是客戶端了?

    不懂沒(méi)關(guān)系,打游戲懂吧?你下載到你電腦你手機(jī)的就是客戶端,你打個(gè)游戲如果沒(méi)有服務(wù)端就不能跟人匹配,這個(gè)懂了吧?

    1.3 基本的工具要拿過(guò)來(lái)吧?

    還知道頭文件吧?

    頭文件就等于是一個(gè)工具箱,需要干啥就可以使用拿頭文件過(guò)來(lái),這樣就可以用里面的工具了。

    那咱們做一個(gè)聊天的軟件就需要一個(gè)工具箱吧,這個(gè)工具箱叫做“.h”,那怎么拿呢?都知道# 吧?

    那就直接把這個(gè)頭文件拿過(guò)來(lái)就好了,代碼就可以寫(xiě)成:#。

    常規(guī)的輸入輸出工具箱也要拿吧?所以就第一步把 stdio.h 也拿過(guò)來(lái),所以這個(gè)服務(wù)端的第一行第二行代碼就寫(xiě)成:

    #include 
    #include

    1.4 開(kāi)始 編程

    不會(huì)了不會(huì)了!是不是一說(shuō) 你就說(shuō)這是個(gè)什么鬼?

    我先說(shuō)一句讓你懵逼的定義“ 就是應(yīng)用之間通信的端點(diǎn)”。懂不懂?

    不懂呀,那我繼續(xù)說(shuō)。

    就是兩個(gè)通信軟件之間的接口,你可以當(dāng)成服務(wù)端是“插座”,客戶端是“插頭”,一插,歐了!這樣不就通電了,這樣說(shuō)你明白了吧?

    當(dāng)然這樣解釋比較片面,但用“抽象”的方式講又不一定能讓大家聽(tīng)得懂,所以你就理解成插頭肯定沒(méi)問(wèn)題。

    1.5 開(kāi)始抬杠我拿三座插兩座插不進(jìn)!

    咱們用的插頭都是有標(biāo)準(zhǔn)的,你想想,沒(méi)有標(biāo)準(zhǔn)怎么那么多電器都可以用常規(guī)的插頭?

    像這個(gè) 這個(gè)通信端口,是有基于一些標(biāo)準(zhǔn)的。例如 TCP/IP這些通信協(xié)議。

    好了,我說(shuō)了TCP/IP可能就會(huì)有同學(xué)問(wèn),這又是什么鬼!沒(méi)關(guān)系,你只需要知道這個(gè)是一個(gè)通信協(xié)議,咱們現(xiàn)在是用 進(jìn)行通信就好,知道 怎么用就行,協(xié)議咱們可不需要現(xiàn)在搞懂,咱們只需要知道 如何運(yùn)用即可。

    二、開(kāi)始敲服務(wù)端代碼2.1 搞清楚使用 進(jìn)行通信的步驟

    編寫(xiě)C語(yǔ)言下的需要經(jīng)過(guò)幾個(gè)步驟:首先對(duì) 進(jìn)行初始化,初始化對(duì) 套接字(也叫套接字)進(jìn)行創(chuàng)建,隨后配合綁定信息,接著進(jìn)行配置信息的bind 綁定;綁定了信息后,通過(guò)該信息進(jìn)行isten 監(jiān)聽(tīng),監(jiān)聽(tīng)后若有鏈接則 連接,再接下來(lái)開(kāi)始使用 接收請(qǐng)求,得到請(qǐng)求后可以選擇接受recv或者send發(fā)送數(shù)據(jù),最后 關(guān)閉 , 最終關(guān)閉。

    簡(jiǎn)單點(diǎn)就是下面的這個(gè)流程:

    不懂了?不懂就慢慢來(lái)嘛。

    這是進(jìn)行 編程的步驟,如果你要問(wèn)為什么要這樣做…我只能回答你規(guī)定的流程就這樣,因?yàn)槟阋M(jìn)行通信,那肯定需要?jiǎng)?chuàng)建一個(gè) ,創(chuàng)建完畢后那么肯定要綁定你要通信的信息,如果你不綁定你怎么知道你要跟誰(shuí)說(shuō)話呢?急著我收到了一個(gè)信息后就等于跟我請(qǐng)求通話,我同意了,咱們就開(kāi)始通信了,通信肯定要發(fā)送信息,那就用send這些方法發(fā)送了,最后面說(shuō)完話我就關(guān)閉這個(gè) 了,那你說(shuō)不是嗎?

    還不懂?那你看下面。

    2.1 第一步初始化

    既然第一步是初始化,那我要初始化什么東西?

    我們需要初始化一個(gè) 類(lèi)型數(shù)據(jù)的對(duì)象。

    什么鬼?又是 又是對(duì)象的,聽(tīng)不懂啊!

    沒(méi)關(guān)系的拉, 其實(shí)就是一個(gè)結(jié)構(gòu)體,咱們?cè)诎咽褂玫墓ぞ呦? 拿過(guò)來(lái)的時(shí)候這個(gè) 結(jié)構(gòu)體就已經(jīng)創(chuàng)建好了,直接使用這個(gè)結(jié)構(gòu)體創(chuàng)建一個(gè)結(jié)構(gòu)體變量就好了。

    的作用就是用來(lái)存儲(chǔ)初始化信息的,就像你打個(gè)游戲初始化創(chuàng)建一個(gè)人,這個(gè)人總得有信息吧,光頭、小眼睛、腿短…對(duì)吧?

    那么我們的代碼就可以寫(xiě)成以下:

    #include 
    #include 
    #include 
     int main(){ 
    	WSADATA wsaData;
     }

    接下來(lái)就可以開(kāi)始初始化了,初始化 有一個(gè)函數(shù)叫做 ,既然是函數(shù)一般都有參數(shù)吧,參數(shù)有哪些呢?

    這個(gè) 方法需要傳入一個(gè) 版本號(hào)c語(yǔ)言寫(xiě)軟件下載,還有一個(gè)用于存儲(chǔ)信息的 結(jié)構(gòu)體。現(xiàn)在我們已經(jīng)知道 的結(jié)構(gòu)體就是上面這個(gè)代碼創(chuàng)建的 結(jié)構(gòu)體變量,那么版本號(hào)又是什么?

    這個(gè)版本號(hào)是說(shuō)明我們使用哪個(gè) 版本, 有一個(gè) 1.1 版本還有一個(gè) 2.2 版本。兩個(gè)版本有不同,1.1 版本只支持 TCP/IP 協(xié)議,還有一個(gè)版本 2.2 支持多個(gè)協(xié)議,這個(gè)時(shí)候你懂用哪個(gè)了吧?

    什么?! 還不懂? 那肯定是全都要呀!

    2.2 版本兼容性之類(lèi)的更好,兼容啥我們不管,反正用多的。

    那直接寫(xiě)成 (2, 2, &)?

    不不不,我們寫(xiě)法有一些不同,需要用一個(gè)函數(shù) 對(duì)版本進(jìn)行生成,就像這樣 ((2, 2), &);,規(guī)定咱們使用 告訴 初始化調(diào)用什么版本。

    那么整個(gè)初始化的代碼就如下所示咯:

    #include
    #include
    #include 
    int main(){
    	WSADATA wsaData;
    	WSAStartup(MAKEWORD(2, 2), &wsadata);
    }

    什么?不懂 & ?來(lái)來(lái)來(lái),我們的漫畫(huà)同學(xué)告訴你是啥意思:

    懂了吧?傳個(gè)地址方便信息存儲(chǔ)。

    2.2 第二步創(chuàng)建

    這一步超級(jí)簡(jiǎn)單,代碼就是這個(gè):

    SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);
    

    我知道你要罵我,寫(xiě)什么是什么鬼。

    好了好了,首先 是一個(gè)的類(lèi)型,還記得 int a 吧?int 是一個(gè)類(lèi)型,那么 肯定就是一個(gè)類(lèi)型了,說(shuō)明創(chuàng)建一個(gè) 類(lèi)型的變量,然后 () 是創(chuàng)建 的函數(shù),這個(gè)沒(méi)毛病吧?

    你說(shuō)是里面的參數(shù)不懂?

    小問(wèn)題了,第一個(gè) 就表示指定 IPV4 ,也就是說(shuō)先給個(gè)網(wǎng)絡(luò)協(xié)議,那么多的網(wǎng)絡(luò)協(xié)議你總要選一個(gè)吧。那為什么要用 IPv4 呢?我只能說(shuō)用這個(gè)東西計(jì)算更快,畢竟咱們做個(gè)聊天軟件是局域網(wǎng)通信,你就理解為,咱們做的東西是個(gè)“小東西”,沒(méi)必要那么大“體量”,迷你更好用,那就用那個(gè) IPV4 了,你想不開(kāi)你也可以用 IPV6 試試。

    那 是什么? 表示咱們進(jìn)行的通信是 TCP 通信,穩(wěn)定可靠。在這里使用 也表示向我們的系統(tǒng),或者你理解成“計(jì)算機(jī)”申請(qǐng)一個(gè)通信的端口,不然系統(tǒng)不給你“開(kāi)個(gè)口子”,我的數(shù)據(jù)怎么傳出去對(duì)吧,不然就是叫破喉嚨都沒(méi)人理我。

    那最后一個(gè)參數(shù) 0 又是什么呢?

    這里就是一個(gè)編號(hào),說(shuō)仔細(xì)點(diǎn)這個(gè)是 所使用的傳輸協(xié)議編號(hào),是不是不明白?其實(shí)這就是一個(gè)編號(hào),不做設(shè)置,但是要給一個(gè)值,所以就給一個(gè) 0 咯。

    2.3 第三步綁定信息

    綁定信息這一步就有點(diǎn)玄了。在這里咱們要了解兩個(gè)結(jié)構(gòu)體,一個(gè)是 ,還有一個(gè)是 。需要注意的是,這兩個(gè)結(jié)構(gòu)體包含的數(shù)據(jù)都是一樣的,是一樣的…

    主要是使用上有區(qū)別。有啥區(qū)別?

    是個(gè)系統(tǒng)用,而 是用來(lái)強(qiáng)制轉(zhuǎn)換 結(jié)構(gòu)體給系統(tǒng)調(diào)用的函數(shù)用。是不是迷茫?不要迷茫,一般都是這樣做,那就這樣做吧。你只需要記住, 保存信息然后就別管了,而 咱們就用來(lái)給參數(shù)給函數(shù)用。

    在 中,咱們使用 結(jié)構(gòu)體綁定監(jiān)聽(tīng)的 IP 信息,首先需要?jiǎng)?chuàng)建這個(gè)結(jié)構(gòu)體:

    struct sockaddr_in sockAddr;
    

    接下來(lái)始綁定端口、IP類(lèi)型,其中 127.0.0.1 表示本機(jī)、1234 表示監(jiān)聽(tīng)端口:

    sockAddr.sin_family = PF_INET; //IPv4
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務(wù)器的IP
    sockAddr.sin_port = htons(1234); //端口
    

    這個(gè)懂沒(méi)懂?

    . 是表示這個(gè)結(jié)構(gòu)體中用于存儲(chǔ)IP協(xié)議的結(jié)構(gòu)體變量, 之前說(shuō)了是 ipV4,表示在這里設(shè)置 ipV4類(lèi)型。

    .. 這里是表示需要綁定的 ip 地址,在這里使用 (“127.0.0.1”) 進(jìn)行指定。那為什么指定個(gè) ip 還需要 ?

    的作用是將一個(gè)字符串格式的ip地址轉(zhuǎn)換成一個(gè)數(shù)字格式。為什么要轉(zhuǎn)換?那肯定是因?yàn)?.. 是一個(gè) 這個(gè)類(lèi)型了。

    最后的 . 是表示要指定某一個(gè)端口,在這里指定 1234 這個(gè)端口。

    所以該部分的代碼就寫(xiě)成這樣了:

    #include
    #include
    #include 
    int main(){
    	WSADATA wsaData;
    	WSAStartup(MAKEWORD(2, 2), &wsadata);
    	
    	SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);
    	
    	struct sockaddr_in sockAddr;
    	sockAddr.sin_family = PF_INET; //IPv4
    	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務(wù)器的IP
    	sockAddr.sin_port = htons(1234); //端口
    }
    

    最后就是綁定一下了:

    bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
    

    在這里 bind() 方法就是表示綁定信息了,第一個(gè)參數(shù)是 就是表示要綁定的 ,然后 (*)& 就是需要綁定的地址,最后一個(gè)就是一個(gè)地址長(zhǎng)度。

    (*)& 我們講過(guò), 就是給函數(shù)使用的, 就是給系統(tǒng)使用的,所以就這樣寫(xiě)就沒(méi)毛病了。

    2.4 監(jiān)聽(tīng)端口

    先讓你懵一下,下面是代碼:

    listen(serverSock, 20);

    簡(jiǎn)單吧? 就是表示監(jiān)聽(tīng),第一個(gè)參數(shù)就是要監(jiān)聽(tīng)的 第二個(gè)就是表示 同時(shí)能處理的最大連接。終于簡(jiǎn)單了這一步,你爽我也爽,還不懂就看下面漫畫(huà)。

    2.5 有人請(qǐng)求聊天?設(shè)置個(gè)接待員

    接下來(lái)就是有人請(qǐng)求給你聊天了,那怎么辦呢?一個(gè)人忙不過(guò)來(lái)呢,那就設(shè)置個(gè)接待員。

    SOCKADDR cIntAddr; 
    int nSize = sizeof(SOCKADDR);
    SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);
    

    函數(shù)就是一個(gè)接待員,有人連接來(lái)敲門(mén)了,就需要去接待,換句比較專(zhuān)業(yè)的話就是 接收一個(gè)套接字中已建立的連接。

    傳入的參數(shù)第一個(gè) 就是一個(gè)已連接的套接字,(*)& 是一個(gè)按照規(guī)定的指向 的指針,所以我猜在前面創(chuàng)建,最后一個(gè)就是所指向這個(gè)指針的長(zhǎng)度咯。

    設(shè)置完后就等于創(chuàng)建了一個(gè)接待員 。

    不過(guò)要注意, 沒(méi)有連接的時(shí)候就會(huì)一直在等待,不然不會(huì)執(zhí)行下面的代碼的。

    這一部分的代碼如下:

    #include
    #include
    #include 
    int main(){
    	WSADATA wsaData;
    	WSAStartup(MAKEWORD(2, 2), &wsadata);
    	
    	SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);
    	
    	struct sockaddr_in sockAddr;
    	sockAddr.sin_family = PF_INET; //IPv4
    	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服務(wù)器的IP
    	sockAddr.sin_port = htons(1234); //端口
    	
    	listen(serverSock, 20);
    	
    	SOCKADDR cIntAddr; 
    	int nSize = sizeof(SOCKADDR);
    	SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);
    }
    

    2.6 開(kāi)始循環(huán)聊天

    在聊天的時(shí)候肯定是需要一個(gè)循環(huán),不用循環(huán)只能發(fā)一次信息就完成了,所以肯定有一個(gè) while:

    while (1) {
    }

    那循環(huán)里面寫(xiě)啥?

    當(dāng)然是寫(xiě)你接收信息和發(fā)送信息的代碼了,我一次性貼上,簡(jiǎn)簡(jiǎn)單單:

    while (1) {
            char sendBuf[50]={"Hello client"};
            char recvBuf[50];
            recv(cIntSock, recvBuf, 50, 0);
            printf("來(lái)自客戶端:");
            printf("%s\n", recvBuf);
            printf_s("請(qǐng)輸入內(nèi)容:");
            scanf("%s",sendBuf);
    		//sendBuf="s";
            //gets_s(sendBuf);
            send(cIntSock, sendBuf, strlen(sendBuf) + 1, 0);
        }
    

    就是一個(gè)字符數(shù)組c語(yǔ)言寫(xiě)軟件下載,用來(lái)輸入自己的要輸入的內(nèi)容。

    主要看recv,recv 接收4個(gè)參數(shù),第一個(gè)參數(shù)是建立的通信、第二個(gè)參數(shù)是是一個(gè)數(shù)組,接收數(shù)據(jù)存放的地方、之后會(huì)緩存大小,最后一個(gè)參數(shù)是指定調(diào)用方式,不用管一般設(shè)置為0。

    就是剛剛從套接字里接受的那個(gè)接待員,現(xiàn)在就用接待員和他說(shuō)話了。

    接著就使用顯示接待員聽(tīng)到的話,簡(jiǎn)簡(jiǎn)單單。

    然后就到我們輸入信息,使用scanf夠簡(jiǎn)單了吧?

    接著使用 send函數(shù)發(fā)送信息就可以了,第一個(gè)就是告訴接待員 要傳達(dá)話了, 就是咱們要說(shuō)的話,第三個(gè)參數(shù)就是咱們說(shuō)的話的長(zhǎng)度,最后一個(gè)依舊是0,不用管。

    這樣就還差最后一步就完成服務(wù)端了,此時(shí)咱們只需要關(guān)閉套接字就可以了,最后還需要清理一下,完整代碼如下了:

    #include
    #include
    #include 
    int main()
    {
        
        WSADATA wsadata;
        WSAStartup(MAKEWORD(2, 2), &wsadata);
        SOCKET serverSock = socket(PF_INET, SOCK_STREAM, 0);
        struct sockaddr_in sockAddr;
        sockAddr.sin_family = PF_INET;
        sockAddr.sin_addr.s_addr = htons(INADDR_ANY);
        sockAddr.sin_port = htons(1234);
        bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
        listen(serverSock, 20);
        SOCKADDR cIntAddr; 
        int nSize = sizeof(SOCKADDR);
        SOCKET cIntSock = accept(serverSock, (SOCKADDR*)&cIntAddr, &nSize);
        while (1) {
        
            char sendBuf[50]={"Hello client"};
            char recvBuf[50];
            recv(cIntSock, recvBuf, 50, 0);
            printf("來(lái)自客戶端:");
            printf("%s\n", recvBuf);
            printf_s("請(qǐng)輸入內(nèi)容:");
            scanf("%s",sendBuf);
            send(cIntSock, sendBuf, strlen(sendBuf) + 1, 0);
        }
    	//關(guān)閉
        closesocket(cIntSock);
        closesocket(serverSock);
        WSACleanup();
        return 0;
    }
    

    三、客戶端編寫(xiě)

    客戶端和服務(wù)端是一樣的你信嗎?

    下面是代碼:

    #include
    #include
    int main()
    {
       WSADATA wsadata;
       int nRes = WSAStartup(MAKEWORD(2, 2), &wsadata);
       SOCKET sock = socket(PF_INET, SOCK_STREAM, 0);
       
       struct sockaddr_in sockAddr;
       
       sockAddr.sin_family = PF_INET; 
       sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //只需要在這里指向服務(wù)器 ip 就可以了 
       sockAddr.sin_port = htons(1234);
       //連接服務(wù)器
       connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
       while (1) {
           char recvBuf[50];
           char sendBuf[50]={"Hello server"};
           printf("跟服務(wù)端說(shuō): ");
           scanf("%s",sendBuf);
           send(sock, sendBuf, strlen(sendBuf) + 1, 0);
           recv(sock, recvBuf, 50, 0);
           printf("服務(wù)端跟你說(shuō): ");
           printf("%s\n", recvBuf);
       }
       closesocket(sock);
       WSACleanup();
       system("pause");
    }
    

    不同的幾個(gè)點(diǎn)只有使用了 連接服務(wù)器就沒(méi)了,難道你說(shuō)不是嗎?

    簡(jiǎn)簡(jiǎn)單單對(duì)吧?那就行,解決。

    下面是演示示例:

    注意 若使用devc復(fù)制代碼都報(bào)錯(cuò),則點(diǎn)擊編譯->編譯選項(xiàng):

    隨后在出現(xiàn)的窗口中添加如下參數(shù):

網(wǎng)站首頁(yè)   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有