热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

socket学习笔记——易犯错误

今天我将分享socket编程,在这条路上的坑,我还能剩多少了!之前再linux系统下进行学习,今天尝试再window下进行编程;区别:后者需要在进行socket编程,加载socket链接库。

今天我将分享socket编程,在这条路上的坑,我还能剩多少了!

之前再linux系统下进行学习,今天尝试再window下进行编程;

区别:后者需要在进行socket编程,加载socket链接库。

server端:

#include
#include<string>
#include 
using namespace std;

#include
#include

#pragma comment(lib,"ws2_32.lib")

#define CONNECT_NUM_MAX 10   //最大连接数
#define MSG_MAX_NUM 256        //接受最大数据数
#define MY_PORT 18000        //端口
#define MY_IP 127.0.0.1        //IP

int main()
{
    //0.加载套接字库
    WSADATA wsaData;
    int ret = 0;
    if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        cout <<"WSAStartup(MAKEWORD(2, 2) execute failed!" << endl;
        return -1;
    }
    if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
    {
        WSACleanup();
        cout <<"WSADATA version is not correct" << endl;
        return -1;
    }
    
    //1.创建套接字
    SOCKET sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockSer == INVALID_SOCKET)
    {
        cout <<"sockSer create fail" << endl;
        return -1;
    }

    //初始化服务器地址族变量
    sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(18000);
    serAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    int serLen = sizeof(SOCKADDR);

    //2.bind链接
    ret = bind(sockSer, (sockaddr *)&serAddr, serLen);
    if (ret == SOCKET_ERROR)
    {
        cout <<"bind execute fail" << endl;
        closesocket(sockSer);
        WSACleanup();
        return -1;
    }

    //3.listen监听
    ret = listen(sockSer, CONNECT_NUM_MAX);
    if (ret == SOCKET_ERROR)
    {
        cout <<"listen execute failed" << endl;
        closesocket(sockSer);
        return -1;
    }
    else
    {
        cout <<"Server is listening on" <":" <"." << endl;
    }

    //4.accept
    sockaddr_in cliAddr;
    int cliLen = sizeof(SOCKADDR);
    SOCKET sockCli = accept(sockSer, (sockaddr *)&cliAddr, &cliLen);
    if (sockCli == INVALID_SOCKET)
    {
        cout <<"Accepted failed with error code:%d\n" < endl;;
        closesocket(sockSer);
        WSACleanup();
        return -1;
    }
    cout <<"Accepted\n" ;

    //5.recv/send
    char sendMsg[MSG_MAX_NUM];
    char recvMsg[MSG_MAX_NUM];
    while (1)
    {
        ZeroMemory(recvMsg, MSG_MAX_NUM);  //对数组进行初始化
        recv(sockCli, recvMsg, 256,0);
        cout <<"Cli:>"< endl;

        ZeroMemory(sendMsg, MSG_MAX_NUM);
        cout <<"Ser:>";
        cin >> sendMsg;
        send(sockCli, sendMsg, strlen(sendMsg)+1, 0);
        
    }

    //6.close
    closesocket(sockSer);
    return 0;
}

坑1:在服务端,我们需要两个SOCKET对象(sockSer和sockCli),前者用来连接、监听和接受客户端请求;后者则在服务端接受客户端请求后返回的sockCli,作为在收发消息的第一个参数。

坑2:必须将客户端和服务器的端口好进行统一。

坑3:sockaddr_in 创建的结构体变量,在配置完成后,connect函数中使用需要进行强转(sockaddr *).

客户端:

#include
#include<string>
#include
using namespace std;

#include
#include

#pragma comment(lib,"ws2_32.lib")

#define MSG_MAX_NUM 256
#define MY_IP 127.0.0.1
#define MY_PORT 18000


int main()
{
    //0.加载套接字库
    WSADATA wsaData;
    int ret = 0;
    if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        cout <<"WSAStartup(MAKEWORD(2, 2), &wsaData) execute failed" << endl;
        return -1;
    }
    if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
    {
        WSACleanup();
        cout <<"WSADATA version is not correct" << endl;
        return -1;
    }
    //1.创建套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockCli == INVALID_SOCKET)
    {
        cout <<"sockCli create failed" << endl;
    }
    //初始化客户端链接服务器端变量
    sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(MY_PORT);
    serAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    int serLen = sizeof(sockaddr);
    //2.connect
    ret = connect(sockCli, (sockaddr *)&serAddr, serLen);
    if (ret != 0)
    {
        cout <<"connect failed" << endl;
        closesocket(sockCli);
        WSACleanup();
        cin.get();
        return -1;
    }
    //3.收发消息
    char sendMsg[MSG_MAX_NUM];
    char recvMsg[MSG_MAX_NUM];
    while (1)
    {
        ZeroMemory(sendMsg, MSG_MAX_NUM);
        cout <<"Cli:>";
        cin >> sendMsg;
        send(sockCli, sendMsg, strlen(sendMsg) + 1, 0);

        ZeroMemory(recvMsg, MSG_MAX_NUM);
        recv(sockCli, recvMsg, 256, 0);
        cout <<"Ser:>" < endl;
    }

    //4.关闭套接字
    closesocket(sockCli);
    return 0;
}

坑1:客户端只要一个SOCKET对象,即针对服务端进行连接,发送数据;

坑2:sockaddr_in 创建的结构体变量,在配置完成后,connect函数中使用需要进行强转(sockaddr *).

 


推荐阅读
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • python中安装并使用redis相关的知识
    本文介绍了在python中安装并使用redis的相关知识,包括redis的数据缓存系统和支持的数据类型,以及在pycharm中安装redis模块和常用的字符串操作。 ... [详细]
author-avatar
iainabaobei_151
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有