1. 程式人生 > >Socket網路程式設計(一)

Socket網路程式設計(一)

此文使用的協議是 TCP

 

    首先要寫入以下程式碼,不然很多函式都用不了

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

 

伺服器端

    第一步我們要匯入套接字型檔。

WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsadata;
int result = WSAStartup(wVersionRequested, &wsadata);

WORD有人可能不知道它是啥

看一看原始碼就可以看到它是這樣定義的

typedef unsigned short WORD   //無符號短整數

 

還有WSAStartup函式,它的原型是這樣的

int WSAStartup(WORD wVersionRequested,LPWSADATA IpWSAData);

第一個引數表示windows socket版本,高位元組是修訂版本號,低位元組是主版本號;

第二個引數記錄windows socket版本的相關資訊,並且是指標變數;

這個函式有返回值,返回0時表示成功,其他值表示失敗。

 

有時我們寫伺服器時為了防止套接字型檔載入錯誤可以寫以下程式碼

if (result != 0)
    {
        printf("套接字載入失敗!");
        return 0;
    }

if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
    {
        printf("套接字版本錯誤!");
        return 0;
    }

當然socket有不同的版本,這裡只是做個示範

 

    第二步建立套接字SOCKET

原始碼是這樣定義的

typedef unsigned int
UINT_PIR typedef UINT_PIR SOCKET

所以SOCKET也是一個無符號整型資料

 

建立套接字要用到socket函式,函式原型是這樣的

SOCKET _stdcall socket(int af,int type,int protocol)

af是address family的縮寫,就是地址簇

type就是使用的協議型別,一共有三種

1、流式套接字(SOCK_STREAM):用到的協議TCP 

2、資料包套接字(SOCK_DGRAM):無連線的,不可靠的UDP

3、原始套接字(SOCK_RAW)

而protocol就是與特定的地址簇相關的協議,一般填0就行了,現在舉個例子

SOCKET sockSrv = socket( AF_INET      //Internet 協議  地址簇
                        SOCK_STREAM, //套接字協議
                        0            //與特定的地址簇相關的協議
);

 

  第三步繫結套接字

//bind繫結套接字,引數一伺服器套接字,引數二伺服器套接字地址,引數三套接字地址大小
SOCKADDR_IN sockaddr;
sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(1234);
if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)))
    {
        printf("繫結套接字失敗!");
        return 0;
    };

那個 INADDR_ANY 表示的是任意地址的意思,因為伺服器的地址是不確定的,所以填這個,當然你想改也可以改,只要改的對,還有埠隨便找個不常用到的就行。

 

    第四步將套接字設定為監聽模式

//   引數一伺服器套接字,引數二等待連線佇列最大長度
if (SOCKET_ERROR == listen(sockSrv, 5))
    {
        printf("監聽失敗!");
        return 0;
    }

 

    第五步接受客戶端

// 引數一伺服器套接字,引數二客戶端套接字,引數三客戶端套接字的長度
SOCKADDR_IN clientaddr;
int nLength = sizeof(SOCKADDR);
SOCKET sockcon = accept(sockSrv, (SOCKADDR*)&clientaddr, &nLength);

 

    第六步傳送/接受資訊

函式原型int_stdcall send(SOCKET s,const char *buf,int len,int flags)

隨便舉個例子

char temp[100];
sprintf(temp, "歡迎 %s 進入聊天室!\n", inet_ntoa(clientaddr.sin_addr));//字串是客戶端的地址
send(sockCon, temp, strlen(temp) + 1, 0);
char temp[256];
recv(sockCon, tmep, 100, 0) 
printf("%s", temp);

 

    最後要記得關閉套接字,不然有時會出現意外情況

closesocket(sock);
WSACleanup();

 

●客戶端

    第一步與伺服器端一樣載入套接字型檔,就不說了

    第二步建立套接字

SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);

    第三步連線伺服器

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//測試所以就用本地的了
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(1234); //埠隨便寫一個1024之後的,也就是不常用的,不過要與伺服器的一樣
//引數一客戶端套接字,引數二伺服器地址資訊,引數三套接字地址大小
if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
    {
        printf("伺服器連線失敗!");
        return 0;
    }

    第四步傳送/接受資訊,與之前的一樣,也不說了

   當然最後也別忘了關閉套接字