日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

《零基础看得懂的C语言入门教程 》——(十三)socket服务端编写

發(fā)布時(shí)間:2023/12/4 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《零基础看得懂的C语言入门教程 》——(十三)socket服务端编写 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、學(xué)習(xí)目標(biāo)

  • 了解C語(yǔ)言的socket的概念
  • 了解C語(yǔ)言socket的使用方法
  • 完成C語(yǔ)言socket服務(wù)端
  • 目錄

    C語(yǔ)言真的很難嗎?那是你沒(méi)看這張圖,化整為零輕松學(xué)習(xí)C語(yǔ)言。

    第一篇:(一)脫離學(xué)習(xí)誤區(qū)
    第二篇:(二)C語(yǔ)言沒(méi)那么難簡(jiǎn)單開發(fā)帶你了解流程
    第三篇:(三)輕輕松松理解第一個(gè)C語(yǔ)言程序
    第四篇:(四)語(yǔ)言的基本數(shù)據(jù)類型及變量
    第五篇:(五)C語(yǔ)言的變量、常量及運(yùn)算
    第六篇:(六)輕輕松松了解C語(yǔ)言的邏輯運(yùn)算
    第七篇:(七)C語(yǔ)言的循環(huán)分分鐘上手
    第八篇:(八)了解基本數(shù)組還不是那么簡(jiǎn)單
    第九篇:(九)C語(yǔ)言二維數(shù)組與循環(huán)嵌套
    第十篇:(十)C語(yǔ)言的指針原來(lái)是這樣
    第十一篇:(十一)C語(yǔ)言自定義函數(shù)真的很簡(jiǎn)單
    第十二篇:(十二)原來(lái)結(jié)構(gòu)體是這么回事
    第十三篇:(十三)socket服務(wù)端編寫

    C語(yǔ)言新手的100個(gè)報(bào)錯(cuò)解法

    推薦

    歡迎大家關(guān)注公眾號(hào),公眾號(hào)每滿1024及1024倍數(shù)則會(huì)抽獎(jiǎng)贈(zèng)送機(jī)械鍵盤一份+IT書籍2份喲~

    二、了解socket 套接字的使用方法

    打個(gè)預(yù)防針:聽不懂概念也會(huì)用的,現(xiàn)在不理解以后肯定會(huì)理解。若讀者是通過(guò)我的基礎(chǔ)教程開始學(xué)到這一篇,我個(gè)人建議盡量多熟悉其中知識(shí)點(diǎn)再學(xué)習(xí)socket,socket設(shè)計(jì)別的知識(shí)內(nèi)容,并且要熟悉基礎(chǔ)語(yǔ)法和特性,不然會(huì)導(dǎo)致一些問(wèn)題。若確實(shí)學(xué)習(xí)了有什么問(wèn)題可以加群?jiǎn)栁襼

    socket也叫做套接字,是在計(jì)算機(jī)網(wǎng)絡(luò)中,不同主機(jī)監(jiān)聽與發(fā)送小心的端點(diǎn),這個(gè)端點(diǎn)是抽象的概念,跟所有不在物理上存在的設(shè)計(jì)一樣,是一中規(guī)則下誕生的存在。

    2.1 使用socket

    以下代碼是在網(wǎng)絡(luò)上找到的代碼,自己進(jìn)行了部分修改。(懶的寫了,哈哈哈)這篇內(nèi)容只注重使用流程,偏向應(yīng)用,過(guò)多的理論知識(shí)不再?gòu)?qiáng)調(diào)。對(duì)于新手學(xué)習(xí)socket我個(gè)人建議是先知道如何“掉包”,先做一個(gè)“掉包俠”完成了整個(gè)流程后才更好的理解其中的問(wèn)題,而且對(duì)于新手來(lái)說(shuō),一些額外的擴(kuò)展知識(shí)并不是每一個(gè)新手都知道的,如果真的需要講解socket的通信,會(huì)設(shè)計(jì)很多網(wǎng)絡(luò)層方面的內(nèi)容,所以我們就先學(xué)會(huì)如何使用socket,之后再來(lái)對(duì)這些知識(shí)進(jìn)行梳理。

    由于socket的實(shí)踐內(nèi)容對(duì)于一部分新手步驟過(guò)于繁瑣,在此則分為上下兩片,一篇為服務(wù)端,一篇為客戶端進(jìn)行通信,相比各位學(xué)習(xí)了服務(wù)端后再次查看客戶端代碼會(huì)覺(jué)得眼前一亮,socket就是用起來(lái)麻煩而已嘛~祝各位碼運(yùn)昌隆!

    socket是基于TCP/IP的,想必一部分的同學(xué)可能對(duì)TCP/IP有所耳熟。確實(shí)TCP/IP字樣在我們學(xué)習(xí)編程時(shí)很常見,他是一種協(xié)議,而協(xié)議是什么呢?協(xié)議是指我們?cè)谧瞿骋患虑榈臅r(shí)候,我們規(guī)定一些細(xì)則、標(biāo)準(zhǔn),方便交流通信,而TCP/IP是協(xié)議的一種,再次我們只需要socket是基于TCP/IP協(xié)議即可,因?yàn)樵诋?dāng)前教程中,談?wù)搮f(xié)議可能對(duì)于某一部分讀者會(huì)有閱讀上的障礙,這是很正常的。其實(shí)我們?cè)诓涣私釺CP/IP協(xié)議的情況下也能進(jìn)行socket通信,因?yàn)槲覀兪褂玫膕ocket函數(shù)是基于TCP/IP的,意思是說(shuō)我們只需要知道socket如何使用即可。

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

    2.2 WSAStartup 初始化

    首先對(duì)WSAStartup 進(jìn)行初始化,WSAStartup 方法接收2個(gè)參數(shù),1個(gè)是WinSock2 的版本號(hào),另一個(gè)是WSADATA 的指針。那么我們需要先創(chuàng)建一個(gè)WSADATA 類型的對(duì)象,代碼為:

    WSADATA wsaData;

    WSADATA 結(jié)構(gòu)用于存儲(chǔ) WSAStartup 初始化后返回的信息,該信息由于使用的是指針,換句話說(shuō)是傳址,那么所存儲(chǔ)的信息將會(huì)保存在WSAStartup 初始化后。

    WSAStartup 接收的第一個(gè)參數(shù)為版本號(hào),版本號(hào)直接可以使用MAKEWORD 生成,MAKEWORD(1, 1)表示選擇版本號(hào)為1。那么WSAStartup 初始化代碼可以寫成:

    WSAStartup(MAKEWORD(1, 1), &wsaData)

    由于WSAStartup等于0則表示初始化失敗,初始化失敗則退出程序,我們可以寫成:

    WSADATA wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {return 0; }

    2.3 socket創(chuàng)建

    socket的創(chuàng)建使用socket方法,socket接收3個(gè)參數(shù),分別是IP類型、通信類型、以及最后一個(gè)參數(shù)可以通過(guò)之前傳遞的參數(shù)使用默認(rèn)類型的配合。IP類型通常使用PF_INET 表示IPV4,通信類型使用TCP,最后一個(gè)參數(shù)使用0表示通過(guò)之前設(shè)置的IP類型與通信類型完成匹配的默認(rèn)選項(xiàng),代碼為:

    SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    創(chuàng)建完畢后,判斷socket是否創(chuàng)建成功,不成功返回-1:

    if (slisten == -1){printf("socket error !");return 0;}

    2.4 IP綁定

    接下來(lái)開始綁定監(jiān)聽的IP地址。創(chuàng)建sockaddr_in結(jié)構(gòu)體變量。

    struct sockaddr_in sin;

    隨后開始綁定端口、IP類型,其中INADDR_ANY表示本機(jī)、6666表示監(jiān)聽端口:

    sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY;

    隨后使用bind進(jìn)行綁定;bind接收3個(gè)參數(shù),一個(gè)是創(chuàng)建的socket、一個(gè)是綁定的IP信息、一個(gè)是IP信息的長(zhǎng)度,綁定失敗則返回-1,代碼為:

    struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) {printf("bind error !");return 0; }

    隨后使用listen進(jìn)行監(jiān)聽,listen接收2個(gè)值,一個(gè)是socket、一個(gè)是隊(duì)列數(shù)量寫個(gè)10就ok了。代碼為:

    if (listen(slisten, 5) == SOCKET_ERROR) {printf("listen error !");return 0; }

    2.5 信息接收

    accept 接收3個(gè)參數(shù),第一個(gè)為socket、第二個(gè)為 sockaddr變量的指針的指針、第三個(gè)為接收sockaddr的長(zhǎng)度。代碼為:

    struct sockaddr_in remoteAddr; int nAddrlen = sizeof(remoteAddr); sClient = accept(s, (SOCKADDR *)&remoteAddr, &nAddrlen);

    使用accpet后將會(huì)進(jìn)行等待,直到有鏈接才會(huì)執(zhí)行之后的代碼。
    隨后使用recv接收客戶端發(fā)送過(guò)來(lái)的文本信息。recv接收4個(gè)參數(shù),第一個(gè)是建立的通信、隨后是一個(gè)數(shù)組,接收數(shù)據(jù)存放的地方、之后會(huì)緩存大小,最后一個(gè)參數(shù)一般設(shè)置為0即可。代碼為:

    char revData[255]; int ret = recv(sClient, revData, 255, 0); printf(revData);

    以上recv函數(shù)中,sClient為使用accpet建立的通信,revData為接收信息的緩存區(qū)、255為長(zhǎng)度。

    隨后發(fā)送一個(gè)數(shù)據(jù)給客戶端,用戶響應(yīng)客戶端的信息請(qǐng)求。使用send可以往已經(jīng)建立的通信通道發(fā)送數(shù)據(jù),send函數(shù)接收4個(gè)參數(shù),第一個(gè)為已經(jīng)建立的通信、第二個(gè)位需要發(fā)送的數(shù)據(jù)、第三個(gè)為發(fā)送的數(shù)據(jù)長(zhǎng)度、最后一個(gè)一般設(shè)置為0。代碼為:

    char * sendData = "你好鴨,我是CSDN 1_bit ,ID是A757291228~\n"; send(sClient, sendData, strlen(sendData), 0);

    以上recv函數(shù)中,sClient為使用accpet建立的通信,sendData為需要發(fā)送的數(shù)據(jù)、255為長(zhǎng)度。
    最后調(diào)用方法關(guān)閉建立的通信即可:

    closesocket(sClient); closesocket(slisten); WSACleanup();

    由于是一次性的通信,程序運(yùn)行完后則會(huì)關(guān)閉,在此我們?cè)诖areturn0前添加停止命令:

    system("pause");

    所有的依賴引用頭文件如下:

    #include <winsock2.h> #include <windows.h> #include<stdio.h> #include<stdlib.h>

    完整代碼如下:

    #include <winsock2.h> #include <windows.h> #include<stdio.h> #include<stdlib.h>int main(int argc, char* argv[]) {//初始化WSADATA WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){return 0;}//創(chuàng)建scoketSOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (slisten == -1){printf("socket error !");return 0;}//綁定端口ip信息struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(8888);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR){printf("bind error !");return 0;}//監(jiān)聽失敗則返回if (listen(slisten, 5) == SOCKET_ERROR){printf("listen error !");return 0;}SOCKET sClient;struct sockaddr_in remoteAddr;int nAddrlen = sizeof(remoteAddr);sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);char revData[255];int ret = recv(sClient, revData, 255, 0);printf(revData);//發(fā)送信息char * sendData = "你好鴨,我是CSDN 1_bit ,ID是A757291228~\n";send(sClient, sendData, strlen(sendData), 0);closesocket(sClient);closesocket(slisten);WSACleanup();system("pause");return 0; }

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

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

    總結(jié)

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

    總結(jié)

    以上是生活随笔為你收集整理的《零基础看得懂的C语言入门教程 》——(十三)socket服务端编写的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。