串口通信+TCP网络通信简单综合实例
串口通信加上TCP网络通信之后就可以简单实现本地设备的联网功能了,哈哈,话不多说,直接上代码。
总体上还是C/S模式,但是这个客户端加上了对串口的操作而已,思路很简单,只不过应用过程中可能会碰到一些棘手的问题,比如和终端的交互协议采用什么,协议的复杂程度如何,通信时的同步问题,稳定性问题等等。这里我们都先不去考虑,下面的代码仅仅只是设备利用串口实现了和远程服务器的通信,还未做任何优化。
1.服务器部分:服务器基本不变,只需要和客户端进行通信即可,和串口无任何交互。所以其代码不变,和TCP网络通信的服务端代码相同。
/*
* 文件:tcp_server.c
* 内容:利用TCP实现客户端和服务器的实时聊天。
* 注 :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argc和argv来实现。
* 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222。
* 编译:gcc tcp_server.c -o ser -lpthread
* 运行:./ser 127.0.0.1 7788 5
*/
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<time.h>
#include<errno.h>
#include<pthread.h>
#include<arpa/inet.h>
#define SPORT 1111
#define CPORT 2222
#define IP "127.0.0.1"
#define MAXLEN 1024
struct network_info
{
struct sockaddr addr;
int addr_len;
int sock;
}target = {0,0,0};
void* myrecv(void* arg)
{
int new_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};
time_t t;
struct network_info netinfo;
netinfo = *((struct network_info*)arg);
new_fd = netinfo.sock;
while(1)
{
memset(buf,'\0',sizeof(buf)-1);
len = recv(new_fd,buf,sizeof(buf) - 1,0);
if(len > 0)
{
t = time(NULL);
printf("&client:%s @%s\n",buf,ctime(&t));
}
else if(len < 0)
{
printf("recv msg error,error code = %d,error msg = %s\n",errno,strerror(errno));
break;
}
else
{
printf("client is quit\n");
close(new_fd);
break;
}
}
}
void* mysend(void* arg)
{
int new_fd = 0,len = 0;
char buf[MAXLEN] = {'\0'};
struct network_info netinfo;
netinfo = *((struct network_info*)arg);
new_fd = netinfo.sock;
while(1)
{
memset(buf,'\0',sizeof(buf));
gets(buf);
if(!strncasecmp(buf,"quit",4))
{
printf("I will close the connect\n");
sleep(1);
close(new_fd);
exit(EXIT_FAILURE);
}
len = sendto(new_fd,buf,strlen(buf),0,(struct sockaddr*)(&(netinfo.addr)),netinfo.addr_len);
if(len < 0)
{
printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));
break;
}
}
}
int main(int argc,char* argv[])
{
int pid = 0,sock_fd = 0,new_fd = 0;
socklen_t len;
struct sockaddr_in self_addr,their_addr;
unsigned int myport,lisnum;
char buf[MAXLEN] = {'\0'};
char ip[17] = {'\0'};
time_t t;
pthread_t pthread1,pthread2;
if(argv[2] && argc >=3)
myport = atoi(argv[2]);
else
myport = SPORT;
if(argv[3] && argc >= 4)
lisnum = atoi(argv[3]);
else
lisnum = 3;
//创建套接字
sock_fd = socket(AF_INET,SOCK_STREAM,0);
if(sock_fd < 0)
{
perror("socket error");
exit(EXIT_FAILURE);
}
//绑定自己的端口号
memset(&self_addr,0,sizeof(self_addr));
self_addr.sin_family = AF_INET;
self_addr.sin_port = htons(myport);
if(argv[1])
self_addr.sin_addr.s_addr = inet_addr(argv[1]);
else
self_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock_fd,(struct sockaddr*)&self_addr,sizeof(self_addr)) == -1)
{
perror("bind error");
exit(EXIT_FAILURE);
}
//监听
if(listen(sock_fd,lisnum) == -1)
{
perror("listen error");
exit(EXIT_FAILURE);
}
//接受客户端的连接请求
memset(&their_addr,0,sizeof(their_addr));
len = sizeof(their_addr);
printf("wait for connect\n");
while(1)
{
if((new_fd = accept(sock_fd,(struct sockaddr*)&their_addr,&len)) == -1)
{
printf("len=%d,new_fd=%d\n",len,new_fd);
perror("accept error");
exit(EXIT_FAILURE);
}
printf("=====================================================================\n");
printf("client connect ok\n");
printf("though i am a server,but if you want to shutdown,please print 'quit'.\n");
printf("=====================================================================\n");
memcpy(&(target.addr),&(their_addr),len);
target.addr_len = len;
target.sock = new_fd;
//创建线程用于进程间通信
pthread_create(&pthread1,NULL,myrecv,(void*)&target);
pthread_create(&pthread2,NULL,mysend,(void*)&target);
}
pthread_join(pthread1,NULL);
pthread_join(pthread2,NULL);
close(new_fd);
close(sock_fd); //关闭套接字
return 0;
}
2.客户端部分(加入了串口操作,而且在多线程操作时仅仅做了简单处理,对了,关于串口操作部分,大家可以去看我转载的串口编程博文)
/*
* 文件:tcp_client.c
* 内容:利用TCP实现客户端和服务器的实时聊天,以及串口操作。
* 注 :服务器的端口号及IP,客户端的端口号及IP的输入通过main函数的argc和argv来实现。
* 未输入端口号的话使用默认端口号,服务器为1111,客户端为2222。
* 编译:gcc tcp_client.c -o cli -lpthread
* 运行:./cli 127.0.0.1 7788(注:这个是服务器端的地址和端口号)
*/
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include <arpa/inet.h>
#include<errno.h>
#include<time.h>
#include<pthread.h>
#include"uart0_open.h"
#include"uart0_init.h"
#include"uart0_send.h"
#include"uart0_recv.h"
#include"uart0_close.h"
#define IP "127.0.0.1"
#define SPORT 1111
#define CPORT 2222
#define MAXLEN 1024
int fd[2] = {0};
void* myrecv() //接收服务器信息后进行处理
{
int len = 0;
char buf[MAXLEN] = {'\0'};
time_t t;
while(1)
{
memset(buf,'\0',sizeof(buf)-1);
len = recv(fd[0],buf,sizeof(buf) - 1,0);
if(len > 0)
{
t = time(NULL);
printf("**********************************\n");
printf("&server:%s\n",buf);
printf("**********************************\n");
UART0_Send(fd[1],buf,strlen(buf)); //收到服务器消息后发给串口
printf("@%s\n",ctime(&t));
}
else if(len < 0)
{
printf("recv msg errno,errno code = %d,errno msg = %s\n",errno,strerror(errno));
break;
}
else
{
printf("connect server error,it will be quit in 3 seconds later...\n");
sleep(3);
exit(EXIT_FAILURE);
}
}
}
void* mysend() //发送信息给服务器
{
int len = 0;
char buf[MAXLEN] = {'\0'};
while(1)
{
memset(buf,'\0',sizeof(buf));
UART0_Recv(fd[1],buf,sizeof(buf)-1); //从串口处获取要发送给服务器的信息
if(!strncasecmp(buf,"quit",4))
{
printf("I will close the connect ...\n");
sleep(1);
exit(EXIT_FAILURE);
}
len = send(fd[0],buf,strlen(buf),0);
if(len < 0)
{
printf("msg is:%s,send failer,errno is %d,errno message is:%s\n",buf,errno,strerror(errno));
break;
}
}
}
int main(int argc,char* argv[])
{
int err = 0;
socklen_t len;
struct sockaddr_in their_addr;
unsigned int their_port;
char buf[MAXLEN] = {0};
pthread_t pthread1,pthread2;
//创建socket
if((fd[0] = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket error");
exit(EXIT_FAILURE);
}
//发送连接服务器的请求
memset(&their_addr,0,sizeof(their_addr));
their_addr.sin_family = AF_INET;
if(argv[2] && argc >= 3)
their_port = atoi(argv[2]);
else
their_port = SPORT;
their_addr.sin_port = htons(their_port);
if(argv[1] && argc >=2)
{
if(inet_aton(argv[1],(struct in_addr *)&their_addr.sin_addr.s_addr) == 0)
{
perror("argv[1]");
exit(EXIT_FAILURE);
}
}
else
their_addr.sin_addr.s_addr = inet_addr(IP);
if(connect(fd[0],(struct sockaddr*)(&their_addr),sizeof(their_addr)) == -1)
{
perror("connect error");
exit(EXIT_FAILURE);
}
//打开串口,返回文件描述符
fd[1] = UART0_Open(fd[1],"/dev/ttyS1");
do {
err = UART0_Init(fd[1],115200,0,8,1,'N');
printf("set port exactly!\n");
} while (-1 == err || -1 == fd[1]);
printf("==============================================\n");
printf("connect success!\n");
printf("if you want to leave,please print 'quit'.\n");
printf("==============================================\n");
pthread_create(&pthread1,NULL,myrecv,NULL); //创建线程
pthread_create(&pthread2,NULL,mysend,NULL);
pthread_join(pthread1,NULL); //等待线程结束
pthread_join(pthread2,NULL);
UART0_Close(fd[1]); //关闭串口
close(fd[0]); //关闭套接字
return 1;
}
结果:记得选择合适版本的交叉编译器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)