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

2023-05-16

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 1024
 
int 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个backlog
    if(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);
 
    //应用程序完成对接的处理后,调用WSACleanup
    if(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 1024
 
int 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;
    }
 
    //Chat
    while(1)
    {
        printf("\n小民:");
        scanf("%s", sendData);
        if(strcmp(sendData, "quit") == 0)   //quit
            break;
        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 1024

using 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:IPv4
	servSock.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 1024

using 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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网络协议与网络编程(双电脑串口通讯) 的相关文章

随机推荐

  • 没有为字符串添加终止符;初始化为‘\0‘

    使用VS2019遇到问题 1 没有为字符串添加终止符 19条消息 消除VS中C6054 可能没有为字符串 34 XXX 34 添加字符串零终止符的警告 wowpH的博客 CSDN博客 可能没有为字符串添加零终止符 2 char a 10 6
  • 安装vue-element-admin报错git clone --mirror -q git://github.com/adobe-webplatform/eve.git C:\Users\Admin

    问题描述 vue element admin项目 执行安装操作时 xff1a 安装依赖 npm install 建议不要直接使用cnpm安装依赖 xff0c 会出现bug xff0c 可以通过如下操作解决npm下载速度慢的问题 由于淘宝 N
  • 添加启动页

    添加启动页 2021 5 7 实验内容 1 为学号后一位同学编写一个简单app 新建一个emptyactivity 在layout的activity main xml中添加如下代码 span class token number 1 spa
  • Python求最大公约数和最小公倍数

    使用辗转相除法求得最大公约数 xff0c 再利用最大公约数求得最小公倍数 辗转相除法求最大公约数 def gcd num1 num2 if num1 num2 61 61 0 return num2 else num1 num2 61 nu
  • matlab实现梯度下降法

    前记 xff1a 大三上学期学了 运筹学 课程 xff0c 里面包含了许多算法和模型 模型就是线性规划及线性规划的对偶理论 xff0c 单纯形法以及它的实际应用 xff1b 整数规划及其解法 xff08 分支定界法 割平面法匈牙利算法 xf
  • 互斥锁、条件变量、信号量浅析

    互斥锁 条件变量 信号量浅析 互斥锁与条件变量 条件变量是为了保证同步 条件变量用在多线程多任务同步的 xff0c 一个线程完成了某一个动作就通过条件变量告诉别的线程 xff0c 别的线程再进行某些动作 xff08 大家都在semtake的
  • Linux中的tty、pts、pty等概念辨析

    Linux中的tty pts pty等概念辨析 基本概念 tty pty pts ptmx tty xff08 终端设备的统称 xff09 xff1a tty一词源于Teletypes xff0c 或teletypewriters xff0
  • 树莓派4B (aarch64) 安装PyTorch 1.8 的可行方案

    树莓派4B aarch64 安装PyTorch 1 8 的可行方案 最终可行方案 试了一堆方案 xff08 源码编译 Fast ai的安装文件等 xff09 之后 xff0c 终于找到一个可行的方案 是在 PyTorch 官方讨论社区的一个
  • Nvidia CUDA初级教程1 CPU体系架构综述

    Nvidia CUDA初级教程1 CPU体系架构综述 视频 xff1a https www bilibili com video BV1kx411m7Fk p 61 2 讲师 xff1a 周斌 本节内容 xff1a 了解现代CPU的架构和性
  • 解决VNC远程连接树莓派,窗口显示不全的问题

    1 vnc连接 xff0c sudo raspi config中7 A5选分辨率就好 或2 通过SSH命令行的方式连接树莓派 xff0c 在命令行输入 xff1a vncserver geometry 1080x1024
  • qt官网下载指导(新手易犯错误)

    一 获取资源 注意这里不要直接百度qt的官网 xff0c 如果直接百度下载会让你注册一个qt的账号 xff0c 并且一般没人下载最新版的qt6 当然也可以下载旧的版本 xff0c 但是由于本人比较愚笨 xff0c 还没有在官网找到qt旧版本
  • AI智能呼叫中心系统,主要应用场景有哪些?

    互联网智能时代 xff0c 销售人员不再每天拨打数百个电话 xff0c 当前呼叫中心电话系统被企业常用在电销行业 金融行业 保险 贷款催收行业等外呼销售行业 由传统的呼叫中心基础上不断的进行升级和改善 xff0c 逐渐演变为人工智能电话外呼
  • ROS:geometry_msgs中 Point32 , Point ,PointStamped 的定义和转换

    ROS geometry msgs中Point32 Point PointStamped 的定义和转换 Point32和Point的定义Point32和Point的转换PointStamped 的定义和转换 本文所用ROS为kinetic版
  • ROS:回调函数不执行

    最近在写一个接收图片消息的节点时 xff0c 遇到了两次回调函数不调用的情况 xff0c 记录一下 循环中有continue被跳过了 具体代码如下 xff1a while ros ok if mat data 61 61 nullptr s
  • Python猜拳游戏

    关键点在于 user input 43 1 3与computer input的值进行比较 xff0c 这样就省掉了对于边界值0和2的单独判断 xff0c 简化了代码 from random import choice def finger
  • ROS:节点发布消息无对应话题名称

    最近在写一个发布里程的节点的时候遇到了 xff0c 发布了消息 xff0c 在ros却没有对应话题情况 通过rostopic list 和 rosnode info 节点名 命令查看 xff0c 均没有对应话题 xff0c 大致代码如下 x
  • 【python安全攻防】python简易端口扫描器

    文章目录 socket套接字optparse模块socket解析主机进行连接获取bannerthreading多线程端口扫描器python nmap端口扫描 对自己看python绝技的一次学习记录 socket套接字 与TCP端口进行交互
  • ROS中geometry_msgs常用消息类型

    官方文档 xff1a geometry msgs Msg Srv Documentation geometry msgs里面所有的消息数据类型 xff1a 节点之间仅支持使用消息通讯 Accel AccelStamped AccelWith
  • 【docker ros】docker 开启自启运行容器中的程序

    前言 xff1a 使用docker大规模部署应用 xff0c 而又需要开机自启 xff0c 自动启动容器中的程序 xff0c 这里以docker ros为例子 xff0c 使用systemctl服务 xff0c 结合shell脚本 xff0
  • 网络协议与网络编程(双电脑串口通讯)

    C C 43 43 网络编程 双电脑串口通讯 在阅读本文前 请确保先查看这篇文章 xff0c 学习有关TCP网编与单电脑信息传输实践 文章目录 C C 43 43 网络编程 双电脑串口通讯 1 让两台电脑连接同一个局域网2 查询IP地址3