winsock

写在开头:

开坑(实现一个网络Game ,emmmm选一个简单的种类,棋类:),象棋)
参照书目:winsock网络编程经络+Unix网络编程以及msdn文档https://msdn.microsoft.com/en-us/library/windows/desktop/ms741394(v=vs.85).aspx
先在windows下实现一个简易C/S,然后在把服务端换在unix端。

因为没有涉及到AI,所以象棋的逻辑比较容易实现,就当是个小程序练习了。主要是学习一下计网。

Unix与windows socket

BSD socket

unix socket是在操作系统中实现的,是操作系统的一部分,程序调用socket是系统调用。
windows是把socket放在动态链接库中。
这种形式只是内部实现不同,对于开发者编写代码都是一致的

winsock

微软根据BSD模型开发的,对windows接口和消息驱动机制很友好,与BSDsocket很多接口一致(简化了移植工作)这里写图片描述

winsock

process(MSDN)

Server

Initialize Winsock.
Create a socket.
Bind the socket.
Listen on the socket for a client.
Accept a connection from a client.
Receive and send data.
Disconnect.

Client

Initialize Winsock.
Create a socket.
Connect to the server.
Send and receive data.
Disconnect.

tips

  • lib
    winsock包含两个版本,winsock2.h为兼容winsock.h的头文件 winsock.h只支持TCP/IP协议栈,winsock2.h +支持多个传输层协议
  • 常量
    winsock程序定义需要许多常量,分别在lib中或者需要自己实现,以方便维护
  • winsock初始化
    使用winsock之前需要WSAStartup初始化WinScok动态链接库。调用失败时返回错误码,每次WSAStartup结束都应该有WSACleanUp
  • port 和ip
    sockaddr_in结构体来初始化
    在linux和windows中,该结构体表示的意义相同,但具体实现细节不同,一下是windows下具体结构及意义
struct sockaddr_in{  
    short sin_family;  
    unsigned short sin_port;  
    struct in_addr sin_addr;  
    char sin_zero[8];  
};

sin_family 地址簇,内核来判断如何解释该地址
sin_port 端口号
sin_addr 32位地址结构体 windows在该结构体使用union结构
sin_zero 填充字节,使之大小等于SOCKADDR

第一个demo

Client
#include <stdio.h>
#include <winsock2.h> 

#pragma comment(lib, "ws2_32") /* WinSock 使用的库函数    */

#define ECHO_DEF_PORT     7 /* 连接的缺省端口 */
#define ECHO_BUF_SIZE   256 /* 缓冲区的大小     */

int main()
{
    WSADATA wsa_data;
    SOCKET echo_soc = 0;      /* socket 句柄 */
    struct sockaddr_in serv_addr;   /* 服务器地址 */
    unsigned short port = ECHO_DEF_PORT;
    int result = 0, send_len = 0;
    char *test_data = "Hello World!", recv_buf[ECHO_BUF_SIZE];
    printf("run");
    const char *Server_Ip = "127.0.0.1";
    const port = 27;
    WSAStartup(MAKEWORD(2,0), &wsa_data);/* 初始化 WinSock资源 */
    send_len = strlen(test_data);

    /* 服务器地址 */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(Server_Ip);

    if (serv_addr.sin_addr.s_addr == INADDR_NONE)
    {
        printf("[ECHO] invalid address\n");
        return -1;
    };

    echo_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */
    result = connect(echo_soc, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    if (result == 0) /* 连接成功 */
    {
        result = send(echo_soc, test_data, send_len, 0);
        result = recv(echo_soc, recv_buf, ECHO_BUF_SIZE, 0);
    }

    if (result > 0)
    {
        recv_buf[result] = 0;
        printf("[Echo Client] receives: \"%s\"\r\n", recv_buf);
    }
    else
        printf("[Echo Client] error : %d.\r\n", WSAGetLastError());

    closesocket(echo_soc);
    WSACleanup();
    int a;

    scanf("%d", &a);
    return 0;
}
Server
#include <stdio.h>
#include <winsock2.h> 

#pragma comment(lib, "ws2_32") /* WinSock 使用的库函数 */

#define ECHO_DEF_PORT     7 /* 侦听的缺省端口 */
#define ECHO_BUF_SIZE   256 /* 缓冲区的大小   */

int main(int argc, char **argv)
{
    WSADATA wsa_data;
    SOCKET  echo_soc = 0,      /* 侦听 socket 句柄  */
            acpt_soc = 0;

    struct sockaddr_in serv_addr,   /* socket的本地地址 */
                       clnt_addr;   /* socket的远端地址 */
    unsigned short port = ECHO_DEF_PORT;
    int result = 0;
    int addr_len = sizeof(struct sockaddr_in);
    char recv_buf[ECHO_BUF_SIZE];

    if (argc == 2)
        port = atoi(argv[1]);

    WSAStartup(MAKEWORD(2,0), &wsa_data);/* 初始化 WinSock资源 */
    echo_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */

    /* socket 的本地地址 */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    result = bind(echo_soc, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (result == SOCKET_ERROR)
    {
        printf("[Echo Server] bind error: %d\n", WSAGetLastError());
        closesocket(echo_soc);
        return -1;
    }

    listen(echo_soc, SOMAXCONN);

    printf("[Echo Server] is running ... ...\n");
    while (1)
    {
        acpt_soc = accept(echo_soc, (struct sockaddr *)&clnt_addr, &addr_len);
        if (acpt_soc == INVALID_SOCKET)
        {
            printf("[Echo Server] accept error: %d\n", WSAGetLastError());
            break;
        }

        result = recv(acpt_soc, recv_buf, ECHO_BUF_SIZE, 0);
        if (result > 0)
        {
            recv_buf[result] = 0;
            printf("[Echo Server] receives: \"%s\", from %s\r\n", 
                   recv_buf, inet_ntoa(clnt_addr.sin_addr));

            result = send(acpt_soc, recv_buf, result, 0);
        }

        closesocket(acpt_soc);
    }

    closesocket(echo_soc);
    WSACleanup();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值