C、C++网络编程(双电脑串口通讯)

在阅读本文前。请确保先查看这篇文章,学习有关TCP网编与单电脑信息传输实践。


文章目录

  • C、C++网络编程(双电脑串口通讯)
    • 1.让两台电脑连接同一个局域网
    • 2.查询IP地址
    • 3.配置端口
    • 4.运行程序
    • 5.程序源码(C)
      • server端
      • client端
    • 6.程序源码(C++)
      • server端
      • client端

本文为华中科技大学 人工智能与自动化学院 自动化1801 魏靖旻编写整理,如有任何错误请及时指正。

在第一篇的基础上,我总结并成功实现了双电脑的即时通讯方式。

其实和单电脑最大的差别只在于两个方面,一个是IPV4地址的确定,一个是Port活动端口号的绑定。在单电脑信息传输基础上,实现双电脑串口通讯其实只需要根据以下的操作 2,3 修改两个参数。

1.让两台电脑连接同一个局域网

2.查询IP地址

a.使用cmd命令提示符,在要运行server端的电脑上查询

  • netstat -ano:

  • ipconfig:

我们注意到此时的IPv4的地址是192.168.43.181 (IPv6和IPv4地址的区别自己百度)

b.然后我们在netstat -ano活动连接中选择本机IPv4的地址对应的端口号

然后我们选择其中的任何一个端口号(:后面的部分,比如说192.168.43.181:139,这个的端口号就是139)

  • TIPS:

至于选择什么状态的PORT,为了减小偶然误差,我在ESTABLISHED、CLOSE_WAIT、TIME_WAIT都成功过,所以自己多试一些端口就出来了。

然后很神奇的是,只要你的这两个程序成功通讯了一次,之后成功率就会大大提高。然后你会发现你选择的端口号和电脑给你配置的端口号可能会不一样,个人觉得应该是电脑自动配置端口,这里影响不大。

同时也说明一下,大部分电脑都有自己的本地端口,如果仅仅在一台电脑上进行通讯则用“127.0.0.1”+任意选择的port即可轻松实现。

3.配置端口

这也是最重要的一步,对应程序源码中的:

unsigned short  Port = 49911;   //端口号,根据用户实际修改

以及

ServerAddr.sin_addr.s_addr = inet_addr("192.168.43.53");  //具体的IP地址,根据用户实际修改

这两步非常重要,后面的参数根据第二部查询IP地址得到的结果进行修改。配置好一个好的端口号,才是成功的前提。

  • 在C/C++程序中,我们将两个源文件配置的端口号PORT和IP_address改成上述所说对应的即可。

  • 客服端(clinet.cpp)和服务器端(server.cpp)的IP地址以及端口号要保持一致。

  • 在上述我的实践过程中,IPv4就是“192.168.43.181”,端口号我选择的是57618。

  • 注意:重新连接新的局域网或者发现程序有问题的时候:

    a.检查本机防火墙是否阻止公用网络访问

    b.要重新在cmd终端输入“netstat -ano”和“ipconfig”查看最新的IPv4的地址的活动接口

    c.之后不断的换IP地址对应的端口,不断地尝试(前文提到过server.cpp和client.cpp两个端要保证IP地址和端口号一致)

4.运行程序


5.程序源码©

二者同时连接了这辆AE86,你敢上吗的热点。

其中我标了注释“//根据用户实际更改”,则按照上述第二步和第三步提到的方式更改

server端
/**  服务器端 Server.c*    */
#include <winsock2.h>
#include <stdio.h>
#include <string.h>#define BUFFSIZE 1024int main(int argc, char**argv)
{int             Ret;WSADATA         wsaData;SOCKET          ListeningSocket;SOCKET          NewConnection;SOCKADDR_IN     ServerAddr;SOCKADDR_IN     ClientAddr;int             ClientAddrLen = sizeof(ClientAddr);unsigned short  Port = 49911; //端口号,根据用户实际修改char            sendData[BUFFSIZE];char            recvData[BUFFSIZE];if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0){printf("WSASTARTUP_ERROR: %d\n", Ret);return 0;}//创建一个套接字来监听客户机连接if((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){printf("SOCKET_ERROR: %d\n", INVALID_SOCKET);return 0;}/** 填充SOCKADDR_IN结构,这个结构将告知bind我们想要在5150端口监听所有接口上的连接*/ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port); //将端口变量从主机字节顺序转换位网络字节顺序ServerAddr.sin_addr.s_addr = inet_addr("192.168.43.53");  //具体的IP地址,根据用户实际修改//ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//使用bind将这个地址信息和套接字绑定起来if(bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR){printf("BIND_ERROR: %d\n", SOCKET_ERROR);return 0;}//监听客户机连接。这里使用5个backlogif(listen(ListeningSocket, 5) == SOCKET_ERROR){printf("LISTEN_ERROR: %d\n", SOCKET_ERROR);return 0;}//连接到达时,接受连接printf("正在接受连接...");if((NewConnection = accept(ListeningSocket, (SOCKADDR *)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET){printf("ACCPET_ERROR: %d\n", INVALID_SOCKET);closesocket(ListeningSocket);return 0;}printf("检测到一个连接: %s 端口:%d\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));//聊天while(1){//接收数据Ret = recv(NewConnection, recvData, BUFFSIZE, 0);if(Ret > 0)printf("小民: %s\n", recvData);else if(Ret < 0)printf("RECV_ERROR: %d\n",  SOCKET_ERROR);else{printf("对方退出程序,聊天结束!");break;}//发送数据printf("\n小魏:");scanf("%s", sendData);if(strcmp(sendData, "quit") == 0)   //退出break;if(send(NewConnection, sendData, BUFFSIZE, 0) == SOCKET_ERROR){printf("消息发送失败!\n");break;}}//从容关闭shutdown(NewConnection, SD_BOTH);//完成新接受的连接后,用closesocket API关闭这些套接字closesocket(NewConnection);closesocket(ListeningSocket);//应用程序完成对接的处理后,调用WSACleanupif(WSACleanup() == SOCKET_ERROR){printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());return 0;}system("pause");return 0;
}
client端

/**  客户端 Client.c**/
#include <winsock2.h>
#include <stdio.h>
#include <string.h>#define BUFFSIZE 1024int main(int argc, char**argv)
{int             Ret;WSADATA         wsaData;SOCKET          s;SOCKADDR_IN     ServerAddr;unsigned short  Port = 49911;    //端口号,根据用户实际修改char            sendData[BUFFSIZE];char            recvData[BUFFSIZE];if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0){printf("WSASTARTUP_ERROR: %d\n", Ret);return 0;}if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){printf("SOCKET_ERROR: %d\n", INVALID_SOCKET);return 0;}ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port);ServerAddr.sin_addr.s_addr = inet_addr("192.168.43.53");  //具体的IP地址,根据用户实际修改//ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");// 这里S_un.S_addr在不同的IDE中可能不一样,然后IPv4地址使用该程序所运行在的PC上的IPv4地址if((connect(s, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))) == SOCKET_ERROR){printf("CONNECT_ERROR: %d\n", SOCKET_ERROR);closesocket(s);return 0;}//Chatwhile(1){printf("\n小民:");scanf("%s", sendData);if(strcmp(sendData, "quit") == 0)   //quitbreak;if(send(s, sendData, BUFFSIZE, 0) == SOCKET_ERROR){printf("消息发送失败!\n");break;}Ret = recv(s, recvData, BUFFSIZE, 0);if(Ret > 0)printf("小魏: %s\n", recvData);else if(Ret < 0)printf("RECV_ERROR: %d\n", SOCKET_ERROR);else{printf("对方退出程序,聊天结束!");break;}}shutdown(s, SD_BOTH);closesocket(s);if(WSACleanup() == SOCKET_ERROR){printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());return 0;}system("pause");return 0;
}

6.程序源码(C++)

其中我标了注释“//根据用户实际更改”,则按照上述第二步和第三步提到的方式更改

server端
#include<iostream>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")//加载 ws2_32.dll#define BUFFSIZE 1024using namespace std;class Socket
{private:SOCKET sock;//套接字sockaddr_in sockAddr;//特定的IP地址unsigned short  Port;//端口号 public:Socket();//构造servSock Socket(int n,Socket servSock);//构造clntSock void usebind2listen();void chat();void close();//~Socket();
}; Socket::Socket()
{this->Port=57618;  //这里根据用户实际更改this->sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);memset(&(this->sockAddr),0,sizeof(this->sockAddr));this->sockAddr.sin_family = PF_INET;  //使用IPv4地址this->sockAddr.sin_addr.s_addr = inet_addr("192.168.43.181");  //具体的IP地址,根据用户实际更改this->sockAddr.sin_port = htons(Port);  //端口
}Socket::Socket(int n,Socket servSock)
{this->sock=accept(servSock.sock,(SOCKADDR*)&(this->sockAddr),&n);//将server的servSock与客户端的sock相连接(二者地址配置相同),并赋给新的套接字clntSock cout<<"检测到一个连接:"<<inet_ntoa(this->sockAddr.sin_addr)<<"端口:"<<ntohs(this->sockAddr.sin_port)<<endl;
}void Socket::usebind2listen()
{bind(this->sock,(SOCKADDR*)&sockAddr,sizeof(SOCKADDR));//将servsock与特定地址绑定 listen(this->sock,5);//监听,主程序运行到此处中断 cout<<"正在接收连接...";
}void Socket::chat()
{int ret;char sendData[BUFFSIZE];char recvData[BUFFSIZE];while(true){//接收数据 ret=recv(this->sock,recvData,BUFFSIZE,0);if(ret>0)cout<<"小民:"<<recvData<<endl; else if(ret<0)cout<<"recv_error"<<SOCKET_ERROR<<endl;else{cout<<"对方退出程序,聊天结束"<<endl;break;}//发送数据cout<<endl<<"小魏:";cin>>sendData;cin.get();//吃掉回车if(strcmp(sendData,"quit")==0){break;} if(send(this->sock,sendData,BUFFSIZE,0)==SOCKET_ERROR){cout<<"发送失败";break;}}shutdown(this->sock, SD_BOTH);
}void Socket::close()
{closesocket(this->sock);//关闭套接字
}int main(int argc,char**argv)
{WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);Socket servSock;//构造套接字对象 PF_INET:IPv4servSock.usebind2listen();//servSock与设定的sockAddr绑定Socket clntSock(sizeof(sockaddr_in),servSock);//重载构造套接字对象,接收客户端请求 clntSock.chat();//聊天 servSock.close();clntSock.close();WSACleanup();//终止 DLL 的使用system("pause");return 0;
}
client端
#include<iostream>
#include<string.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")//加载 ws2_32.dll#define BUFFSIZE 1024using namespace std;class CSocket
{private:SOCKET sock;//套接字sockaddr_in sockAddr;//特定的IP地址unsigned short  Port;//端口号 public:CSocket();void useconnect();void userecieve(char *str);void chat();void close();//~CSocket();
};CSocket::CSocket()
{this->Port=57618;  //这里根据用户实际更改this->sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);memset(&(this->sockAddr),0,sizeof(this->sockAddr));this->sockAddr.sin_family = PF_INET;  //使用IPv4地址this->sockAddr.sin_addr.s_addr = inet_addr("192.168.43.181");  //具体的IP地址,根据用户实际更改this->sockAddr.sin_port = htons(Port);  //端口
}void CSocket::useconnect()
{connect(sock,(SOCKADDR*)&(this->sockAddr),sizeof(SOCKADDR));//套接字与地址建立连接,与服务器的accept相对应
}void CSocket::chat()
{int ret;char sendData[BUFFSIZE];char recvData[BUFFSIZE];while(true){   //发送数据cout<<endl<<"小民:";cin>>sendData;cin.get();//吃掉回车if(strcmp(sendData,"quit")==0){break;} if(send(this->sock,sendData,BUFFSIZE,0)==SOCKET_ERROR){cout<<"发送失败";break;}//接收数据 ret=recv(this->sock,recvData,BUFFSIZE,0);if(ret>0)cout<<"小魏:"<<recvData<<endl; else if(ret<0)cout<<"recv_error"<<SOCKET_ERROR<<endl;else{cout<<"对方退出程序,聊天结束"<<endl;break;}}shutdown(this->sock, SD_BOTH);
}void CSocket::close()
{closesocket(this->sock);
}int main(int argc,char**argv)
{WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);CSocket sock;sock.useconnect();sock.chat();sock.close();WSACleanup();system("pause");return 0;
}

网络协议与网络编程(双电脑串口通讯)相关推荐

  1. 网络协议 11 - Socket 编程(下):眼见为实耳听为虚

    网络协议 11 - Socket 编程(下):眼见为实耳听为虚 原文:网络协议 11 - Socket 编程(下):眼见为实耳听为虚 系列文章传送门: 网络协议 1 - 概述 网络协议 2 - IP ...

  2. 电脑串口通讯调试台达VFD-M变频器的方法和教程

    电脑串口通讯调试台达VFD-M变频器的方法和教程 所需硬件:USB转485转换头,台达VFD-M变频器. 控制效果:通过串口调试助手,modbus rtu通讯方式,控制变频器的正反转,停止,频率设定, ...

  3. c语言stm32串口控制单片机,基于STM32F103C8T6单片机电脑串口通讯控灯设计(原理图+程序+论文)...

    题目:基于STM32F103C8T6单片机电脑串口通讯控灯设计 内容要求: 一. 任务 通信是指不同的独立系统利用线路互相交换数据,它的主要目的是将数据从一端传送到另一端,实现数据的交换.在现代工业控 ...

  4. 九、网络协议和网络编程

    1.TCP建立连接的过程. 在谈及TCP建立连接和释放连接过程,先来简单认识一下TCP报文段首部格式的的几个名词(这里只是简单说明,具体请查看相关教程)  序列号seq:占4个字节,用来标记数据段的顺 ...

  5. 【计算机网络】——通信协议综述(网络协议、网络分层、ifconfige命令行、DHCP与PXE)

    一.为什么学习网络协议 协议三要素: 人类和计算机之间需要沟通的协议,只有通过这种协议,计算机才知道我们想让它做什么. 可以看得出,计算机语言作为程序员控制一台计算机工作的协议,具备了协议的三要素. ...

  6. 网络协议与网络传输相关知识

    网络协议 1.HTTP/2.0相比较于HTTP/1.1,有哪几项主要改进(请写出至少三种)? HTTP 2.0 的出现,相比于 HTTP 1.x ,大幅度的提升了 web 性能.在与 HTTP/1.1 ...

  7. 软件网络协议测试,网络协议测试方法是什么

    在计算机网络的发展历程中,协议一直处于核心地位.从ARPAnet发展到Internet,其关键环节就是形成了国际标准化的协议.协议是计算机网络和分布式系统中各种通信实体之间相互交换信息所必须遵守的一组 ...

  8. 常见的网络协议与网络要素的介绍

    常用的网络协议有 TCP/IP 协议.IPX/SPX 协议.NetBEUI 协议.HTTP 协议.FTP 协议等.网络通信协议是一种网络通用语言,为连接不同操作系统和不同硬件体系结构的互联网络提供通信 ...

  9. OSI七层网络协议,网络协议的层次结构

      网络协议的层次结构: 1. OSI七层模型:OSI(Open System Interconnect),即开放式系统互联 第一层:物理层 作用:透明地传输比特流.为数据端设备提供传送数据通路.传输 ...

最新文章

  1. 苏黎世联邦理工学院SML课题组招收统计机器学习全奖博士生
  2. flutter 实现不可滚动的ListView构建器
  3. Android组件之Service
  4. 理解SQL SERVER中的分区表
  5. 伏安特性曲线实验报告_电化学扩散层,Cottrell equation,取样电流伏安法
  6. 为什么shell脚本第一行要#!/bin/sh
  7. 【VBA编程】06.控制语句
  8. Hadoop集群(第10期副刊)_常用MySQL数据库命令
  9. project euler Problem 52
  10. 中fifo算法_java线程池,工作窃取算法
  11. 移动磁盘哪种格式更好
  12. vc10的C2664和C2065错误
  13. Unicode字符编码
  14. 2022.3.27 学习韩顺平老师java基础
  15. 电力线通信技术的发展
  16. 爬虫自动定时获取查重结果并将结果发送至指定邮箱
  17. 用色环图帮你搞定配色
  18. 栈evaluate-reverse-polish-notation-leetcode练习题
  19. 二十六篇,Linux库文件(动态库和静态库)的制作。
  20. Destoon增加内容页的浏览历史记录

热门文章

  1. 在VS2010中ActiveX控件注册方法,使用regsvr32命令
  2. Lesson 18 He often does this! 他经常干这种事!
  3. 靶机17 GROTESQUE: 3.0.1
  4. bandit(13-34)
  5. Python之禅——传说中的蛇宗总纲
  6. 关于xp系统下的IIS 500错误
  7. mxnet-Gluon(一):mxnet-Gluon 入门
  8. 创客平台靠什么盈利?
  9. 密码学基础 上机实验4 ElGamal的Python实现(求解原根)
  10. OpenHarmony介绍及相关资料