WinSock入门(一)

最基本的Winsock的程序。

本来应该作为博客的代码Wiki部分进行保存,而不是一篇博文的。无奈自建博客的计划迟迟没有开动的迹象,先忍忍。

这两个文件完成了最简单的Winsock的例子:服务器端进行侦听,客户端发起连接,发送数据,服务器端收到数据后进行反馈。

下面是客户端的代码文件:

// ClientProcess.cpp
#include "StdAfx.h"
#include "ClientProcess.h"

#include <iostream>
#include <WinSock2.h>

#pragma comment(lib, "Wsock32")

using namespace std;
 
#define CHECK_SOCK_ERROR(funName, cond)                        \
    do {                                                       \
        if (cond)                                              \
        {                                                      \
            cout<<#funName" error: "<<WSAGetLastError()<<endl; \
            return;                                            \
        }                                                      \
    }while(0)


void PrepairWinsock(){
    WSADATA wsaData;
    WORD    sockVersion = MAKEWORD(2, 0);
    if (0 != WSAStartup(sockVersion, &wsaData))
    {
        cout<<"WSAStartup Error!"<<endl;
    }
}

void CleanWinsock(){
    WSACleanup();
}

void SentData(){
    SOCKET clientSocket = NULL;

    // type 0 is TCP/IP
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);

    int serverPort = 4444;
    SOCKADDR_IN serverSockAddr;
    serverSockAddr.sin_family           = AF_INET;
    serverSockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 服务器端是同一主机
    serverSockAddr.sin_port             = htons(serverPort);      // 端口为1024到5000之间的任意值

    int ret = connect(clientSocket, (LPSOCKADDR)&serverSockAddr, sizeof(serverSockAddr));
    CHECK_SOCK_ERROR(connect, ret);

    char strSend[] = "test data!";
    ret = send(clientSocket, strSend, sizeof(strSend), 0);
    CHECK_SOCK_ERROR(send, SOCKET_ERROR == ret);

    int const BUFF_SIZE = 256;
    char buff[BUFF_SIZE] = {0};
    cout<<"Start recv"<<endl;
    ret = recv(clientSocket, buff, BUFF_SIZE, 0);
    CHECK_SOCK_ERROR(recv, SOCKET_ERROR == ret);

    cout<<"Recv Data: "<<buff<<endl;
    
    closesocket(clientSocket);
}

void SendDataByWinSock(){
    PrepairWinsock();
    SentData();
    CleanWinsock();
}

另一个是服务器端的代码:

//ServerProcess.cpp
#include "StdAfx.h"
#include "ServerProcess.h"
#include <iostream>
#include <string>
#include <WinSock2.h>

#pragma comment(lib, "Wsock32")

using namespace std;

#define CHECK_SOCK_ERROR(funName, cond)                        \
    do {                                                       \
        if (cond)                                              \
        {                                                      \
            cout<<#funName" error: "<<WSAGetLastError()<<endl; \
            return;                                            \
        }                                                      \
    }while(0)

void PrepairWinsock(){
    WSADATA wsaData;
    WORD    sockVersion = MAKEWORD(2, 0);
    if (0 != WSAStartup(sockVersion, &wsaData))
    {
        cout<<"WSAStartup Error!"<<endl;
    }
}

void CleanWinsock(){
    WSACleanup();
}

void WaitForData(){
    SOCKET serverSocket = NULL;

    // type 0 is TCP/IP
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);

    int serverPort = 4444;
    SOCKADDR_IN serverSockAddr;
    serverSockAddr.sin_family           = AF_INET;
    serverSockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    serverSockAddr.sin_port             = htons(serverPort); // 端口为1024到5000之间的任意值
    
    cout<<"Start bind"<<endl;
    int ret = bind(serverSocket, (LPSOCKADDR)&serverSockAddr, sizeof(serverSockAddr));
    CHECK_SOCK_ERROR(bind, SOCKET_ERROR == ret);

    cout<<"Start listen"<<endl;
    ret = listen(serverSocket, 2);
    CHECK_SOCK_ERROR(listen, SOCKET_ERROR == ret);

    cout<<"Start accept"<<endl;
    // accept 会返回另一个socket,这个socket用于通信,而原来的
    // sockte继续进行侦听。
    SOCKET dataCommuSock = accept(serverSocket, NULL, NULL);
    CHECK_SOCK_ERROR(accept, INVALID_SOCKET == dataCommuSock);

    int const BUFF_SIZE = 256;
    char buff[BUFF_SIZE] = {0};
    cout<<"Start recv"<<endl;
    ret = recv(dataCommuSock, buff, BUFF_SIZE, 0);
    CHECK_SOCK_ERROR(recv, (0 == ret) || (SOCKET_ERROR == ret));

    string strRecv(buff);
    cout<<"recv message : "<<strRecv<<endl;

    strRecv += strRecv;
    send(dataCommuSock, strRecv.c_str(), strRecv.size(), 0);
    CHECK_SOCK_ERROR(send, SOCKET_ERROR == ret);

    cout<<"close socket"<<endl;
    closesocket(serverSocket);
    closesocket(dataCommuSock);
}

void GetDataByWinSock(){
    PrepairWinsock();
    WaitForData();
    CleanWinsock();
}

这里面的对socket的调用都是阻塞式的。

 

posted on 2012-02-12 22:51  唐风思琪  阅读(1114)  评论(0编辑  收藏  举报

导航