socket筆記

網(wǎng)絡(luò)進(jìn)程通信

1.通過網(wǎng)絡(luò)層“ip地址”可以唯一標(biāo)識網(wǎng)絡(luò)中的主機(jī)
2.傳輸層的“協(xié)議+端口”可以唯一標(biāo)識主機(jī)中的應(yīng)用程序
所以通過 ip地址+協(xié)議+端口 就可以確定標(biāo)識網(wǎng)絡(luò)的進(jìn)程了,網(wǎng)絡(luò)中的進(jìn)程通信就可以利用這個標(biāo)志與其它進(jìn)程進(jìn)行交互

socket

socket字面意思就是套接字
網(wǎng)絡(luò)中的進(jìn)程是通過socket來通信的

客戶端和服務(wù)段通信流程圖(借用網(wǎng)上的圖片使用)

image.png

基本是流程就這樣:

服務(wù)器:創(chuàng)建套接字->綁定協(xié)議地址族(ip地址,端口,通信協(xié)議)->監(jiān)聽客戶端排隊的最大連接個數(shù)->等待接收客戶端連接->數(shù)據(jù)交互->關(guān)閉套接字
客戶端:創(chuàng)建套接字-》連接服務(wù)器地址族-》進(jìn)入數(shù)據(jù)交互-》關(guān)閉套接字

根據(jù)上面的思路,簡單的示例如下:

SeverSocket

#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")
int main(){
    //請求協(xié)議版本
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
        printf("請求協(xié)議版本失?。n");
        return -1;
    }

    //創(chuàng)建socket(協(xié)議版本,數(shù)據(jù)類型,協(xié)議)
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == -1){
        printf("創(chuàng)建socket失??!\n");
        WSACleanup();
        return -2;
    }
    printf("創(chuàng)建socket成功!\n");
    //創(chuàng)建協(xié)議地址族
    SOCKADDR_IN addr = { 0 };
    addr.sin_family = AF_INET;//協(xié)議版本
    addr.sin_addr.S_un.S_addr = inet_addr("10.10.12.52");//ip地址
    addr.sin_port = htons(10010);//端口,建議自定義端口使用10000之后的,以為之前的端口可能被其他應(yīng)用程序占用


    //綁定
    int r = bind(serverSocket, (sockaddr*)&addr, sizeof addr);
    if (r == -1){
        printf("bind失敗!\n");
        closesocket(serverSocket);
        WSACleanup();
        return -2;
    }
    printf("bind成功!\n");
    //監(jiān)聽
    r = listen(serverSocket, 10);
    if (r == -1){
        printf("listen失敗!\n");
        closesocket(serverSocket);
        WSACleanup();
        return -2;
    }
    printf("listen成功!\n");

    //等待客戶端連接 客戶端協(xié)議地址族
    SOCKADDR_IN cAddr = { 0 };
    int len = sizeof cAddr;
    SOCKET clinetSocket = accept(serverSocket, (sockaddr*)&cAddr, &len);
    if (clinetSocket == -1){
        printf("服務(wù)器宕機(jī)了!\n");
        //關(guān)閉socket
        closesocket(serverSocket);
        //清除協(xié)議信息
        WSACleanup();
        return -2;
    }
    printf("有客戶端連接到服務(wù)器了:%s!\n", inet_ntoa(cAddr.sin_addr));

    //通信
    char buff[1024];
    while (1){
        r = recv(clinetSocket, buff, 1023, NULL);
        if (r > 0){
            buff[r] = 0;
            printf(">>>>%s\n", buff);
        }
    }


    getchar();
    //system("pause");
    return 0;
}

ClientSocket

#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")
int main(){
    //1.請求協(xié)議版本
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
        printf("請求協(xié)議版本失?。n");
        return -1;
    }

    //2.創(chuàng)建socket
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (clientSocket == -1){
        printf("創(chuàng)建socket失??!\n");
        WSACleanup();
        return -2;
    }
    printf("創(chuàng)建socket成功!\n");
    //3.創(chuàng)建協(xié)議地址族
    SOCKADDR_IN addr = { 0 };
    addr.sin_family = AF_INET;
    addr.sin_addr.S_un.S_addr = inet_addr("10.10.12.52");
    addr.sin_port = htons(10010);

    //4.連接服務(wù)器
    int r = connect(clientSocket, (sockaddr*)&addr, sizeof addr);
    if (r == -1){
        printf("連接服務(wù)器失??!\n");
        return -2;
    }
    printf("連接服務(wù)器成功!\n");
    //5.通信
    char buff[1024];
    while (1){
        memset(buff, 0, 1024);
        printf("你想說什么:\n");
        scanf("%s", buff);
        send(clientSocket, buff, strlen(buff), NULL);
    }

    getchar();
    //system("pause");
    return 0;
}

運行結(jié)果:


image.png

可以在這個簡單的例子基礎(chǔ)上進(jìn)行優(yōu)化,實現(xiàn)多玩家的連接服務(wù)器,進(jìn)行數(shù)據(jù)交互

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容