• 记Windows下初次使用dev C++进行socket编程过程


             记初次接触socket编程,在devC++使用Winsock进行socket编程的一个过程,通过在devC++创建2个项目分别是server、client程序项目,感受通过socket使client与server的一次通讯。

    1.新建项目与往常不同,不单单是需要创建一个C文件,更是要在连接库中添加 libws2_32
    在项目管理中的属性配置连接库,然后在项目中新建server.c
    面向连接的C/S程序工作流程(TCP)
    1. 使用WSAStartup()函数检查系统协议栈安装情况
    2. 使用socket()函数创建服务器端通信套接字
    3. 使用bind()函数将创建的套接字与服务器地址绑定
    4. 使用listen()函数使服务器套接字做好接收连接请求准备
    5. 使用accept()接收来自客户端由connect()函数发出的连接请
    6. 根据连接请求建立连接后,使用send()函数发送数据,或者使用recv()函数接收数据
    7. 使用closesocket()函数关闭套接字(可以先用shutdown()函数先关闭读写通道)
    8. 最后调用WSACleanup()函数结束Winsock Sockets API
    server代码:
    #pragma comment(lib,"ws2_32.lib")
    #include <Winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define DEFAULT_PORT 5050 //服务端默认端口
    int main(int argc, char* argv[])
    {
    int iPort = DEFAULT_PORT;
    WSADATA wsaData;
    SOCKET sListen,sAccept;
    int iLen; //客户机地址长度
    int iSend; //发送数据长度
    char buf[] = "I am a server"; //要发送给客户的信息
    struct sockaddr_in ser,cli; //服务器和客户的地址
    if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
    {
    printf("Failed to load Winsock.
    "); //Winsock 初始化错误
    return -1;
    }
    sListen = socket(AF_INET,SOCK_STREAM,0); //创建服务器端套接字
    if(sListen == INVALID_SOCKET)
    {
    printf("socket() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    //以下初始化服务器端地址
    ser.sin_family = AF_INET; //使用 IP 地址族
    ser.sin_port = htons(iPort); //主机序端口号转换为网络字节序端口号
    ser.sin_addr.s_addr = htonl(INADDR_ANY); //主机序 IP 地址转换为网络字节序主机地址
    //使用系统指定的 IP 地址 INADDR_ANY
    if(bind(sListen,(LPSOCKADDR)&ser,sizeof(ser)) == SOCKET_ERROR) //套接定与地址的绑定
    {
    printf("bind() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    if(listen(sListen,5) == SOCKET_ERROR) //进入监听状态
    {
    printf("lisiten() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    iLen = sizeof(cli); //初始化客户端地址长度参数
    while(1) //进入循环等待客户的连接请求
    {
    sAccept = accept(sListen,(struct sockaddr *)&cli,&iLen);
    if(sAccept == INVALID_SOCKET)
    {
    printf("accept() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    printf("Accepted client IP:[%s],port:[%d]
    ",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
    //输出客户端 IP 地址和端口号
    iSend = send(sAccept,buf,sizeof(buf),0); //给客户端发送信息
    if(iSend == SOCKET_ERROR) //错误处理
    {
    printf("send() Failed: %d
    ",WSAGetLastError());
    break;
    }
    else if(iSend == 0)
    {
    break;
    }
    else
    {
    printf("send() byte: %d
    ",iSend); //输出发送成功字节数
    }
    closesocket(sAccept);
    }
    closesocket(sListen); //关闭 socket
    WSACleanup(); //输出发送成功字节数
    return 0;
    }
    2.保存最后构建并运行这个项目,编译生成 server.exe。
    server项目结构:
    3.以同样的方法新建 client 工程,编译生成 client.exe。
    面向连接的C/S程序工作流程(TCP)
    1. 使用WSAStartup()函数检查系统协议栈安装情况
    2. 使用socket()函数创建客户端套接字
    3. 使用connect()函数发出也服务器建立连接的请求(调用前可以不用bind()端口号,由系统自动完成)
    4. 连接建立后使用send()函数发送数据,或使用recv()函数接收数据
    5. 使用closesocet()函数关闭套接字
    6. 最后调用WSACleanup()函数,结束Winsock Sockets API
    client代码:
    #pragma comment(lib,"ws2_32.lib")
    #include <Winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define DATA_BUFFER 1024 //默认缓冲区大小
    int main(int argc, char * argv[])
    {
    WSADATA wsaData;
    SOCKET sClient;
    int iPort = 5050;
    int iLen; //从服务器端接收的数据长度
    char buf[DATA_BUFFER]; //接收缓冲区
    struct sockaddr_in ser; //服务器端地址
    if(argc<2) //判断参数输入是否正确:client [Server IP]
    {
    printf("Usage: client [server IP address]
    "); //命令行提示
    return -1;
    }
    memset(buf,0,sizeof(buf)); //初始化接收缓冲区
    if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
    {
    printf("Failed to load Winsock.
    "); //Winsock 初始化错误
    return -1;
    }
    ser.sin_family = AF_INET; //初始化服务器地址信息
    ser.sin_port = htons(iPort); //端口转换为网络字节序
    ser.sin_addr.s_addr = inet_addr(argv[1]); //IP 地址转换为网络字节序
    sClient = socket(AF_INET,SOCK_STREAM,0); //创建客户端流式套接字
    if(sClient == INVALID_SOCKET)
    {
    printf("socket() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    //请求与服务器端建立 TCP 连接
    if(connect(sClient,(struct sockaddr *)&ser,sizeof(ser)) == INVALID_SOCKET)
    {
    printf("connect() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    else
    {
    iLen = recv(sClient,buf,sizeof(buf),0); //从服务器端接收数据
    if(iLen == 0)
    return -1;
    else if(iLen == SOCKET_ERROR)
    {
    printf("recv() Failed: %d
    ",WSAGetLastError());
    return -1;
    }
    else
    printf("recv() data from server: %s
    ",buf); // 输出接收数据
    }
    closesocket(sClient); //关闭 socket
    WSACleanup();
    return 0;
    }
    4.运行结果:
    启动 server.exe,最后启动 client.ex 程序与服务器通信
    (客户端每次连接,会收到来自服务端的消息,服务端这边对每次到来的访问将打印访问ip和端口)
  • 相关阅读:
    Netty解决粘包和拆包问题的四种方案
    springboot 1.4 CXF配置
    聊聊springboot2的embeded container的配置改动
    MFC函数——CWnd::OnCreate
    《开发专家 Visual C 开发入行真功夫》笔记
    MFC中UpdateData()函数的使用
    Visual Studio 2008 添加MScomm控件的方法
    Visual Studio 2008 调试运行Bug记录
    《VS2010/MFC编程入门教程》——读书笔记
    《C++程序设计教程——给予Visual Studio 2008》读书笔记3章
  • 原文地址:https://www.cnblogs.com/liqiujiong/p/9607453.html
Copyright © 2020-2023  润新知