socket串口通信

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据同步 1个月
简介:

SocketServer:

#include <arpa/inet.h>  #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #define SERVPORT 3333    /*服务器监听端口号 */ #define BACKLOG 10    /* 最大同时连接请求数 */ #define MAXDATASIZE 100    /*每次最大数据传输量 */  void process_cli(int sockfd ,  struct sockaddr_in  saSockAddr);  int main(int argc, const char * argv[])  {     int recvbytes;     int sock_fd,client_fd;    /*sock_fd:监听socket;client_fd:数据传输socket */     int sin_size;     struct sockaddr_in my_addr;    /* 本机地址信息 */     struct sockaddr_in remote_addr;    /* 客户端地址信息 */     if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {         perror("socket创建出错!");         exit(1);     }     my_addr.sin_family=AF_INET;     my_addr.sin_port=htons(SERVPORT);     my_addr.sin_addr.s_addr = INADDR_ANY;     bzero(&(my_addr.sin_zero),8);     if(bind(sock_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {         perror("bind出错!");         exit(1);     }     if(listen(sock_fd, BACKLOG) == -1) {         perror("listen出错!");                  exit(1);     }     sin_size = sizeof(struct sockaddr_in);          int i = 0;     char buffer[MAXDATASIZE];     int pid;     while(1)     {         if((client_fd = accept(sock_fd, (struct sockaddr *)&remote_addr, &sin_size)) == -1) {             perror("accept出错");             exit(1);         }         printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr));                  process_cli(client_fd , my_addr);                  close(sock_fd);     }      return 0; }  /*---------------------------------  程序名∶process_cli  参数  : int sockfd 连接的socket  struct sockaddr_in saSockaddr  客户地址信息  返回 ∶ 无  描述 ∶ 显示接收到的客户端传来的信息  反转送回客户端  ----------------------------------*/ void process_cli(int sockfd ,  struct sockaddr_in  saSockAddr) {          char szRevBuf[MAXDATASIZE] , szSendBuf[MAXDATASIZE] ;     int i = 0;     int iLen ;      memset(szRevBuf,'\0',sizeof(szRevBuf));     /*循环接收*/      while(iLen = recv(sockfd , szRevBuf , MAXDATASIZE , 0))     {         if(iLen == -1){             perror("recv出错!");         }         szRevBuf[iLen] = '\0';         printf("收到客户信息:%s",szRevBuf);         if(i >= 100)             return;         sprintf(szSendBuf, "第%d次给客户端发消息", i);         send(sockfd , szSendBuf , strlen(szSendBuf),0);         memset(szRevBuf,'\0',sizeof(szRevBuf));         i++;     } }

SocketClient:

#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define SERVPORT 3333 #define MAXDATASIZE 100    /*每次最大数据传输量 */  void process(int sockfd ,  struct sockaddr_in  saSockAddr);  int main(int argc, const char * argv[]) {     int sock_fd;     struct hostent *host;     struct sockaddr_in serv_addr;      if((host=gethostbyname("127.0.0.1")) == NULL) {         herror("gethostbyname出错!");         exit(1);     }     if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {         perror("socket创建出错!");         exit(1);     }     serv_addr.sin_family=AF_INET;     serv_addr.sin_port=htons(SERVPORT);     serv_addr.sin_addr = *((struct in_addr *)host->h_addr);     bzero(&(serv_addr.sin_zero),8);     if(connect(sock_fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1) {         perror("connect出错!");         exit(1);     }     process(sock_fd ,serv_addr);          close(sock_fd);      return 0; }  void process(int sockfd ,  struct sockaddr_in  saSockAddr) {     char buf[MAXDATASIZE];     int recvbytes;          int i= 0;     while(1)     {         if(i >= 100)             return;                  sprintf(buf, "第%d次给服务端发消息\n", i);         if(send(sockfd, buf, 100, 0) == -1) {             perror("send出错!");         }                  memset(buf,'\0',sizeof(buf));         if((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {             perror("recv出错!");             exit(1);         }         buf[recvbytes] = '\0';         printf("收到服务端信息: %s\n",buf);                  i++;     } }

资料:

OSI中的层

功能

TCP/IP协议族

应用层

文件传输,电子邮件,文件服务,虚拟终端

TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

表示层

翻译、加密、压缩

没有协议

会话层

对话控制、建立同步点(续传)

没有协议

传输层

端口寻址、分段重组、流量、差错控制

TCP,UDP

网络层

逻辑寻址、路由选择

IP,ICMP,OSPF,EIGRP,IGMP,RIP,ARP,RARP

数据链路层

成帧、物理寻址、流量,差错,接入控制

SLIP,CSLIP,PPP,MTU

物理层

设置网络拓扑结构、比特传输、位同步

ISO2110,IEEE802,IEEE802.2


一、基本socket函数
Linux
系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打
开文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。


1socket函数
syntax:
   int socket(int domain, int type, int protocol);
功能说明:
   
调用成功,返回socket文件描述符;失败,返回-1,并设置errno
参数说明:
domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;
type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字
protocol通常赋值"0"
  两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。


2
bind函数
syntax:  
   int bind(int sock_fd,struct sockaddr_in *my_addr, intaddrlen);
功能说明:
   
将套接字和指定的端口相连。成功返回0,否则,返回-1,并置errno.
参数说明:
    sock_fd
是调用socket函数返回值,
my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;
structsockaddr_in结构类型是用来保存socket信息的:
structsockaddr_in {
shortint sin_family;
unsignedshort int sin_port;
structin_addr sin_addr;
unsignedchar sin_zero[8];
};
    addrlen
sockaddr的长度。


3connect函数
syntax:  
    int connect(int sock_fd, struct sockaddr *serv_addr,intaddrlen);
功能说明:
   
客户端发送服务请求。成功返回0,否则返回-1,并置errno
参数说明:
   sock_fd 
socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是结构sockaddr_in的长度。


4listen函数
syntax:
   int listen(int sock_fd
 int backlog);
功能说明:
   
等待指定的端口的出现客户端连接。调用成功返回0,否则,返回-1,并置errno.
参数说明:
   sock_fd 
socket()函数返回值;
   backlog
指定在请求队列中允许的最大请求数


5accecpt函数
syntax:  
   int accept(int sock_fd, struct sockadd_in* addr, intaddrlen);
功能说明:
   
用于接受客户端的服务请求,成功返回新的套接字描述符,失败返回-1,并置errno
参数说明:
   sock_fd
是被监听的socket描述符,
   addr
通常是一个指向sockaddr_in变量的指针,
   addrlen
是结构sockaddr_in的长度。


6write函数
syntax:
    ssize_t write(int fd,const void *buf,size_t nbytes)
功能说明:
    write
函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量.
    
在网络程序中,当我们向套接字文件描述符写时有俩种可能:
      1)write
的返回值大于0,表示写了部分或者是全部的数据.
      2)
返回的值小于0,此时出现了错误.需要根据错误类型来处理.
        
如果错误为EINTR表示在写的时候出现了中断错误.
        
如果错误为EPIPE表示网络连接出现了问题.

 


7read函数
syntax:
    ssize_t read(int fd,void *buf,size_t nbyte)
函数说明:
    read
函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是表示已经读到文件的结束了,小于0表示出现了错误.
    
如果错误为EINTR说明读是由中断引起的,
    
如果错误是ECONNREST表示网络连接出了问题.



8
close函数
syntax:
int close(sock_fd);
说明:
当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:
函数运行成功返回0,否则返回-1


二、socket编程的其他函数说明
1
网络字节顺序及其转换函数
1
网络字节顺序
每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,
一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数,
以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。
2
有关的转换函数
* unsigned short int htons
unsigned short int hostshort):
主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes
* unsigned long int htonl
unsigned long int hostlong):
主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes
* unsigned short int ntohs
unsigned short int netshort):
网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes
* unsigned long int ntohl
unsigned long int netlong):
网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes
注:以上函数原型定义在netinet/in.h
2
IP地址转换
有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换
1 unsigned long intinet_addr(const char * cp):该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:struct sockaddr_in ina
ina.sin_addr.s_addr=inet_addr("202.206.17.101")
该函数成功时:返回转换结果;失败时返回常量INADDR_NONE,该常量=-1,二进制的无符号整数-1相当于255.255.255.255,这是一个广播地址,所以在程序中调用iner_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数inet_aton()。
2int inet_atonconst char * cp,structin_addr * inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。
3 char * inet_ntoastruct in-addr in):将32位二进制形式的IP地址转换为数字点形式的IP地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。
3
、字节处理函数
Socket
地址是多字节数据,不是以空字符结尾的,这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据,一组以bbyte)开头,是和BSD系统兼容的函数,另一组以mem(内存)开头,是ANSI C提供的函数。
b开头的函数有:
1 void bzerovoid * s,int n):将参数s指定的内存的前n个字节设置为0,通常它用来将套接字地址清0
2 void bcopyconst void * srcvoid * destint n):从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。
3 int bcmpconst void * s1const void * s2int n):比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容,如果相同则返回0,否则返回非0
注:以上函数的原型定义在strings.h中。
mem开头的函数有:
1 void * memsetvoid * sint csize_t n):将参数s指定的内存区域的前n个字节设置为参数c的内容。
2 void * memcpyvoid * destconst void * srcsize_t n):功能同bcopy(),区别:函数bcopy()能处理参数src和参数dest所指定的区域有重叠的情况,memcpy()则不能。
4 int memcmpconst void * s1const void * s2size_t n):比较参数s1和参数s2指定区域的前n个字节内容,如果相同则返回0,否则返回非0
注:以上函数的原型定义在string.h中。





















本文转自蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366501,如需转载请自行联系原作者


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
4月前
|
缓存 监控 Java
Java Socket编程最佳实践:优化客户端-服务器通信性能
【6月更文挑战第21天】Java Socket编程优化涉及识别性能瓶颈,如网络延迟和CPU计算。使用非阻塞I/O(NIO)和多路复用技术提升并发处理能力,减少线程上下文切换。缓存利用可减少I/O操作,异步I/O(AIO)进一步提高效率。持续监控系统性能是关键。通过实践这些策略,开发者能构建高效稳定的通信系统。
149 1
|
2月前
|
Python
python socket 简单通信
python socket 简单通信
40 1
|
2月前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
151 0
|
4月前
|
Java 应用服务中间件 开发者
【实战指南】Java Socket编程:构建高效的客户端-服务器通信
【6月更文挑战第21天】Java Socket编程用于构建客户端-服务器通信。`Socket`和`ServerSocket`类分别处理两端的连接。实战案例展示了一个简单的聊天应用,服务器监听端口,接收客户端连接,并使用多线程处理每个客户端消息。客户端连接服务器,发送并接收消息。了解这些基础,加上错误处理和优化,能帮你开始构建高效网络应用。
344 10
|
4月前
|
IDE Java 开发工具
从零开始学Java Socket编程:客户端与服务器通信实战
【6月更文挑战第21天】Java Socket编程教程带你从零开始构建简单的客户端-服务器通信。安装JDK后,在命令行分别运行`SimpleServer`和`SimpleClient`。服务器监听端口,接收并回显客户端消息;客户端连接服务器,发送“Hello, Server!”并显示服务器响应。这是网络通信基础,为更复杂的网络应用打下基础。开始你的Socket编程之旅吧!
56 3
|
4月前
|
Java 数据挖掘 开发者
Java网络编程进阶:Socket通信的高级特性与应用
【6月更文挑战第21天】Java Socket通信是分布式应用的基础,涉及高级特性如多路复用(Selector)和零拷贝,提升效率与响应速度。结合NIO和AIO,适用于高并发场景如游戏服务器和实时数据分析。示例展示了基于NIO的多路复用服务器实现。随着技术发展,WebSockets、HTTP/2、QUIC等新协议正变革网络通信,掌握Socket高级特性为应对未来挑战准备。
43 1
|
4月前
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
86 0
|
4月前
|
安全 Java 网络安全
Java Socket编程教程:构建安全可靠的客户端-服务器通信
【6月更文挑战第21天】构建安全的Java Socket通信涉及SSL/TLS加密、异常处理和重连策略。示例中,`SecureServer`使用SSLServerSocketFactory创建加密连接,而`ReliableClient`展示异常捕获与自动重连。理解安全意识,如防数据截获和中间人攻击,是首要步骤。通过良好的编程实践,确保网络应用在复杂环境中稳定且安全。
86 0
|
1月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【8月更文挑战第27天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。