<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Gofanの后花园</title>
  
  
  <link href="https://garthsitu.github.io/atom.xml" rel="self"/>
  
  <link href="https://garthsitu.github.io/"/>
  <updated>2024-03-12T15:10:00.000Z</updated>
  <id>https://garthsitu.github.io/</id>
  
  <author>
    <name>Gofan</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Windows下使用C++&#92;winsock库实现tcp客户端通信</title>
    <link href="https://garthsitu.github.io/posts/837472e.html"/>
    <id>https://garthsitu.github.io/posts/837472e.html</id>
    <published>2024-03-12T15:10:00.000Z</published>
    <updated>2024-03-12T15:10:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1>编程思路</h1><h2 id="第一步">第一步</h2><p>创建一个<code>WASDATA</code>结构体变量，用于存储关于<code>Winsock</code>库的信息；初始化<code>Winsock</code>库。</p><h2 id="第二步">第二步</h2><p>创建TCP套接字。</p><h2 id="第三步">第三步</h2><p>创建<code>sockaddr_in</code>结构体变量，用于储存服务器地址信息。里面包括设置地址族、IP地址、端口号。</p><h2 id="第四步">第四步</h2><p>调用<code>connect</code>函数连接服务器。</p><h2 id="通信">通信</h2><p>调<code>send</code>函数发送数据</p><p>调<code>recv</code>函数接收数据</p><h1>实现代码</h1><h2 id="头文件部分">头文件部分</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;winsock2.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;ws2tcpip.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> comment(lib, <span class="string">&quot;ws2_32.lib&quot;</span>) <span class="comment">//告诉编译器链接Winsock库</span></span></span><br></pre></td></tr></table></figure><h2 id="main-函数部分">main 函数部分</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    WSADATA wsaData; <span class="comment">//创建一个结构体变量，用于存储关于Winsock库的信息</span></span><br><span class="line">    <span class="type">int</span> result = <span class="built_in">WSAStartup</span>(<span class="built_in">MAKEWORD</span>(<span class="number">2</span>, <span class="number">2</span>), &amp;wsaData); <span class="comment">//初始化Winsock库，指定版本号2.2，检查返回值</span></span><br><span class="line">    <span class="keyword">if</span> (result != <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;WSAStartup failed: &quot;</span> &lt;&lt; result &lt;&lt; std::endl; <span class="comment">//输出错误信息并退出程序</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    SOCKET connectSocket = <span class="built_in">socket</span>(AF_INET, SOCK_STREAM, IPPROTO_TCP); <span class="comment">//创建一个TCP套接字，检查返回值</span></span><br><span class="line">    <span class="keyword">if</span> (connectSocket == INVALID_SOCKET)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;socket failed with error: &quot;</span> &lt;&lt; <span class="built_in">WSAGetLastError</span>() &lt;&lt; std::endl; <span class="comment">//输出错误信息并退出程序</span></span><br><span class="line">        <span class="built_in">WSACleanup</span>(); <span class="comment">//清除Winsock库</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    sockaddr_in service; <span class="comment">//创建一个结构体变量，用于存储服务器地址信息</span></span><br><span class="line">    service.sin_family = AF_INET; <span class="comment">//指定地址族为IPv4</span></span><br><span class="line">    <span class="built_in">inet_pton</span>(AF_INET, <span class="string">&quot;127.0.0.1&quot;</span>, &amp;service.sin_addr); <span class="comment">//将字符串类型的IP地址转换为二进制网络字节序的IP地址，并存储在结构体中</span></span><br><span class="line">    service.sin_port = <span class="built_in">htons</span>(<span class="number">6666</span>); <span class="comment">//将端口号从主机字节序转换为网络字节序，并存储在结构体中</span></span><br><span class="line"></span><br><span class="line">    result = <span class="built_in">connect</span>(connectSocket, (SOCKADDR*)&amp;service, <span class="built_in">sizeof</span>(service)); <span class="comment">//连接到服务器，检查返回值</span></span><br><span class="line">    <span class="keyword">if</span> (result == SOCKET_ERROR)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;connect failed with error: &quot;</span> &lt;&lt; <span class="built_in">WSAGetLastError</span>() &lt;&lt; std::endl; <span class="comment">//输出错误信息并退出程序</span></span><br><span class="line">        <span class="built_in">closesocket</span>(connectSocket); <span class="comment">//关闭套接字</span></span><br><span class="line">        <span class="built_in">WSACleanup</span>(); <span class="comment">//清除Winsock库</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Connected to server.&quot;</span> &lt;&lt; std::endl; <span class="comment">//连接成功，输出消息</span></span><br><span class="line"></span><br><span class="line">    <span class="type">char</span> sendBuffer[<span class="number">1024</span>] = <span class="string">&quot;Hello, server!&quot;</span>; <span class="comment">//创建发送缓冲区，存储待发送的数据</span></span><br><span class="line">    result = <span class="built_in">send</span>(connectSocket, sendBuffer, <span class="built_in">sizeof</span>(sendBuffer), <span class="number">0</span>); <span class="comment">//向服务器发送数据，检查返回值</span></span><br><span class="line">    <span class="keyword">if</span> (result == SOCKET_ERROR)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;send failed with error: &quot;</span> &lt;&lt; <span class="built_in">WSAGetLastError</span>() &lt;&lt; std::endl; <span class="comment">//输出错误信息并退出程序</span></span><br><span class="line">        <span class="built_in">closesocket</span>(connectSocket); <span class="comment">//关闭套接字</span></span><br><span class="line">        <span class="built_in">WSACleanup</span>(); <span class="comment">//清除Winsock库</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">char</span> recvBuffer[<span class="number">1024</span>]; <span class="comment">//创建接收缓冲区，用于存储从服务器接收到的数据</span></span><br><span class="line">    result = <span class="built_in">recv</span>(connectSocket, recvBuffer, <span class="built_in">sizeof</span>(recvBuffer), <span class="number">0</span>); <span class="comment">//从服务器接收数据，检查返回值</span></span><br><span class="line">    <span class="keyword">if</span> (result == SOCKET_ERROR)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;recv failed with error: &quot;</span> &lt;&lt; <span class="built_in">WSAGetLastError</span>() &lt;&lt; std::endl; <span class="comment">//输出错误信息并退出程序</span></span><br><span class="line">        <span class="built_in">closesocket</span>(connectSocket); <span class="comment">//关闭套接字</span></span><br><span class="line">        <span class="built_in">WSACleanup</span>(); <span class="comment">//清除Winsock库</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Received message from server: &quot;</span> &lt;&lt; recvBuffer &lt;&lt; std::endl; <span class="comment">//输出从服务器收到的数据</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">closesocket</span>(connectSocket); <span class="comment">//关闭套接字</span></span><br><span class="line">    <span class="built_in">WSACleanup</span>(); <span class="comment">//清除Winsock库</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>注意事项(debug过程)</h1><p>运行代码之前要使用网络调试助手打开TCP服务端，注意端口号、IP地址这些要匹配。</p><p>代码主要是C语言，C++部分是控制台输入输出的，如果纯C语言就include&lt;stdio.h&gt;,用<code>printf</code>、<code>scanf</code>这些库函数替换就好了。</p><p>以上代码使用VS的编译器上是可以直接运行的，但是如果是使用MinGW gcc/g++就会出现问题。我们来看报错。</p><p><img src="https://img2023.cnblogs.com/blog/2706518/202403/2706518-20240312231047428-2043679741.png" alt=""></p><h3 id="1-inet-pton函数未定义。">1.<code>inet_pton</code>函数未定义。</h3><p>inet_pton函数将点分十进制串转换成网络字节序二进制值，此函数对IPv4地址和IPv6地址都能处理，在Windows下只需包含<code>ws2tcpip.h</code>头文件就行了</p><p>根据网上的说法，是因为Windows gcc 默认的 <code>_WIN32_WINNT </code>是 502 Windows Server 2003，所以解决方案是重新定义<code>_WIN32_WINNT</code>，在<code>ws2tcpip.h</code>前加入</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifdef</span>  _WIN32_WINNT</span></span><br><span class="line"><span class="meta">#<span class="keyword">undef</span>  _WIN32_WINNT</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span>  _WIN32_WINNT  0x0600</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure><p>还有一个方法，那就是。。。不用<code>inet_pton()</code>函数了，用别的IP地址转换函数——<code>inet_addr()</code></p><p>这样<a href="##%E7%AC%AC%E4%B8%89%E6%AD%A5">第三步</a>的代码改为</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sockaddr_in service; <span class="comment">//创建一个结构体变量，用于存储服务器地址信息</span></span><br><span class="line">service.sin_family = AF_INET; <span class="comment">//指定地址族为IPv4</span></span><br><span class="line">service.sin_addr.S_un.S_addr = <span class="built_in">inet_addr</span>(<span class="string">&quot;127.0.0.1&quot;</span>); <span class="comment">//将点分十进制转化32位unsigned int</span></span><br><span class="line">service.sin_port = <span class="built_in">htons</span>(<span class="number">6666</span>); <span class="comment">//将端口号从主机字节序转换为网络字节序，并存储在结构体中</span></span><br></pre></td></tr></table></figure><p>这个问题就解决了。</p><h3 id="2-链接动态库问题undefined-reference-to-imp-WSAStartup">2. 链接动态库问题<code>undefined reference to __imp_WSAStartup</code></h3><p>在vs中直接加入</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> comment(lib, <span class="string">&quot;ws2_32.lib&quot;</span>)</span></span><br></pre></td></tr></table></figure><p>就可以链接winsock动态库，不知道为什么gcc编译器不行。1 问题解决后，报如下错误：</p><p><img src="https://img2023.cnblogs.com/blog/2706518/202403/2706518-20240312231046835-212927369.png" alt=""></p><p>所以在vscode的配置tasks.json的<code>args</code>参数加一个：<code>&quot;-lwsock32&quot;</code>，在编译命令中指定链接就可以了。</p><p>对于如果找不到<code>_imp_inet_pton</code>的话，就需要再加<code>args</code>参数：<code>&quot;-lws2_32&quot;</code>。</p><p>然后就能连上TCP服务器了。</p><p><img src="https://img2023.cnblogs.com/blog/2706518/202403/2706518-20240312231045995-1085506737.png" alt=""></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;编程思路&lt;/h1&gt;
&lt;h2 id=&quot;第一步&quot;&gt;第一步&lt;/h2&gt;
&lt;p&gt;创建一个&lt;code&gt;WASDATA&lt;/code&gt;结构体变量，用于存储关于&lt;code&gt;Winsock&lt;/code&gt;库的信息；初始化&lt;code&gt;Winsock&lt;/code&gt;库。&lt;/p&gt;
&lt;h2 id=&quot;第二</summary>
      
    
    
    
    <category term="编程语言" scheme="https://garthsitu.github.io/categories/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/"/>
    
    
    <category term="C++" scheme="https://garthsitu.github.io/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>在U盘&#92;移动硬盘上搭建MySQL数据库</title>
    <link href="https://garthsitu.github.io/posts/837471e.html"/>
    <id>https://garthsitu.github.io/posts/837471e.html</id>
    <published>2022-11-18T15:24:00.000Z</published>
    <updated>2022-11-19T10:30:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>由于近期要使用到mysql数据库，但又不想直接安装到电脑上，一是由于临时使用，不想占用电脑存储空间，二是想安装到移动硬盘上，这样也可以在别的电脑使用。具体安装过程参考视频[<a href="https://www.bilibili.com/video/BV1NS4y1g7Vm/?spm_id_from=333.1007.top_right_bar_window_history.content.click&amp;vd_source=af711b70456f58d89b195f5fd884561c">1]</a>，视频教程很详细，此处就不再过多赘述，简单记录一下我在安装使用过程中遇到的坑。</p><ul><li>安装完成后，退出powershell，此时再次打开powershell或cmd，输入<code>mysql -u root -p</code>，再输入password，会出现 Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)，这时候需要输入<code>mysqld --console</code>，启动数据库后才可以正常使用</li></ul><p><img src="https://pic2.zhimg.com/v2-cb6ca75172fca73fac7f813a436a89d3_1440w.jpg" alt="img"></p><p>注：输入<code>mysqld --console</code>需要在对应的文件夹路径。</p><ul><li>在使用过程MySQL过程中窗口要保持，把窗口关闭后mysql也关闭了，就不能正常使用了。</li></ul><p>如果需要在命令行操作mysql数据库，需要另外打开一个cmd或powershell窗口，再次输入<code>mysql -u root -p</code>和密码，就可以进行其他命令操作。</p><p><img src="https://pic4.zhimg.com/v2-74315ebe110b50acbe6f4f8f2abf3b55_1440w.jpg" alt="img"></p><p>使用MySQL数据库软件进行连接</p><p><img src="https://picx.zhimg.com/v2-fda1f32ff8e0490b68c4cdfadb3afe83_1440w.jpg" alt="img"></p><p>Navicat for mysql连接</p><h2 id="参考">参考</h2><ol><li><a href="https://www.bilibili.com/video/BV1NS4y1g7Vm/?spm_id_from=333.1007.top_right_bar_window_history.content.click&amp;vd_source=af711b70456f58d89b195f5fd884561c">【演示】5分钟快速在U盘上搭建可随身带走的MySQL数据库_哔哩哔哩_bilibili</a></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;由于近期要使用到mysql数据库，但又不想直接安装到电脑上，一是由于临时使用，不想占用电脑存储空间，二是想安装到移动硬盘上，这样也可以在别的电脑使用。具体安装过程参考视频[&lt;a href=&quot;https://www.bilibili.com/video/BV1NS4y1g7V</summary>
      
    
    
    
    <category term="MySQL数据库" scheme="https://garthsitu.github.io/categories/MySQL%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
    <category term="MySQL" scheme="https://garthsitu.github.io/tags/MySQL/"/>
    
    <category term="数据库" scheme="https://garthsitu.github.io/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
  </entry>
  
</feed>
