如何通过Socket通信控制LED
对于树莓派来说,可以通过ssh和电脑进行互联,所以一般的应用来说,不需要socket通信,只要打开ssh在树莓派上运行写好的Python或者C程序即可。但是,有的project需要多个sensor,如果仅仅通过打开多个ssh来运行不同程序,这样sensor搜集的数据就不直观,因此就需要在PC上建立一个Server来和树莓派通信,从而可以把所有sensor以及其他devices需要的信号都集中显示在一个PC端的程序上。如果会网页编程的话,在树莓派上建立一个WEB服务器应该也很好实现这个功能。如果不会网页编程,那只好使用socket通信了。最简单的开始,也就是通过socket控制LED的亮与熄。
下面是Server端的程序:# TCP-Serverimport socket
# 1 创建 socket 对象
s = socketsocket(socketAF_INET, socketSOCK_STREAM)
# 2 将 socket 绑定到指定地址 (本机地址)address = ('1921681102', 8889)
sbind(address)
# 3 接收连接请求# listen(backlog), The backlog argument specifies the maximum number of queued connections and should be at least 0;
# the maximum value is system-dependent (usually 5), the minimum value is forced to 0
slisten(5)
print 'Waiting for connection'
# 4 等待客户请求一个连接# 调用 accept 方法时,socket 会进入 "waiting" 状态。
# accept方法返回一个含有两个元素的元组 (connection, address)。
# 第一个元素 connection 是新的 socket 对象,服务器必须通过它与客户通信;
# 第二个元素 address 是客户的 Internet 地址。
new_s, addr = saccept()
print 'Got connect from', addr
# 5 处理:服务器和客户端通过 send 和 recv 方法通信
command = ' '
print ('Please enter 1 to turn on the led, 2 to turn off the led,3 to disconnect the communication:')
while True:
command = raw_input()
new_ssend(command)
data = new_srecv(512)
print data if data == 'Communication is disconnected':
break
# 6 传输结束,关闭连接
new_sclose()
sclose()
接下来是Client端程序:
# TCP-Clientimport RPiGPIO as GPIO
import time
import socket
address = ('1921681102', 8889)
s = socketsocket(socketAF_INET, socketSOCK_STREAM)
sconnect(address)
GPIOsetmode(GPIOBCM)
GPIOsetwarnings(False)
GPIOsetup(27, GPIOOUT)
GPIOsetup(17, GPIOOUT)
GPIOoutput(17, False)
GPIOoutput(27, False)
while True:
command = srecv(512)
if command == '1':
GPIOoutput(27, True)
GPIOoutput(17, False)
ssend('Command 1 received by client')
print "Command is ", command
elif command == '2':
GPIOoutput(27, False)
GPIOoutput(17, True)
ssend('Command 2 received by client')
print "Command is ", command
elif command == '3':
ssend('Communication is disconnected')
print "Command is ", command
break
else:
ssend('Please enter 1, 2 or 3')
print "Command is ", commandsclose()
我们只需要在PC上运行Server的程序,在Raspberry Pi上运行Client的程序便可以控制LED的亮与熄了,很简单。
用socket实现进程通信 ,和socket的普通用法一样,只不过服务端IP为127001 而已
下面附上代码示例:
//服务器端代码 进程1#include <stdioh>
#include <stdlibh>
#include <stringh>
#include <sys/typesh>
#include <netinet/inh>
#include <sys/socketh>
#include <arpa/ineth>
#include <unistdh>
int main(int argc, char argv[])
{
int sock;
//sendto中使用的对方地址
struct sockaddr_in toAddr;
//在recvfrom中使用的对方主机地址
struct sockaddr_in fromAddr;
int recvLen;
unsigned int addrLen;
char recvBuffer[128];
sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if(sock < 0)
{
printf("创建套接字失败了\r\n");
exit(0);
}
memset(&fromAddr,0,sizeof(fromAddr));
fromAddrsin_family=AF_INET;
fromAddrsin_addrs_addr=htonl(INADDR_ANY);
fromAddrsin_port = htons(4000);
if(bind(sock,(struct sockaddr)&fromAddr,sizeof(fromAddr))<0)
{
printf("bind() 函数使用失败了\r\n");
close(sock);
exit(1);
}
while(1){
addrLen = sizeof(toAddr);
if((recvLen = recvfrom(sock,recvBuffer,128,0,(struct sockaddr)&toAddr,&addrLen))<0)
{
printf("()recvfrom()函数使用失败了\r\n");
close(sock);
exit(1);
}
if(sendto(sock,recvBuffer,recvLen,0,(struct sockaddr)&toAddr,sizeof(toAddr))!=recvLen){
printf("sendto fail\r\n");
close(sock);
exit(0);
}
return 0;
}
} //客户端代码 进程2
#include <stdioh>
#include <stdlibh>
#include <stringh>
#include <sys/typesh>
#include <netinet/inh>
#include <sys/socketh>
#include <arpa/ineth>
#include <unistdh>int main(int argc, char argv[])
{
if(argc < 2)
{
printf("请输入要传送的内容\r\n");
exit(0);
}
int sock;
//sendto中使用的对方地址
struct sockaddr_in toAddr;
//在recvfrom中使用的对方主机地址
struct sockaddr_in fromAddr;unsigned int fromLen;
char recvBuffer[128];
sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if(sock < 0)
{
printf("创建套接字失败了\r\n");
exit(1);
}memset(&toAddr,0,sizeof(toAddr));
toAddrsin_family=AF_INET;
toAddrsin_addrs_addr=inet_addr("127001");
toAddrsin_port = htons(4000);if(sendto(sock,argv[1],strlen(argv[1]),0,(struct sockaddr)&toAddr,sizeof(toAddr)) != strlen(argv[1]))
{
printf("sendto() 函数使用失败了\r\n");
close(sock);
exit(1);
}fromLen = sizeof(fromAddr);
if(recvfrom(sock,recvBuffer,128,0,(struct sockaddr)&fromAddr,&fromLen)<0)
{
printf("()recvfrom()函数使用失败了\r\n");
close(sock);
exit(1);
}
printf("recvfrom() result:%s\r\n",recvBuffer);
close(sock);}
当然可以通信,
不论任何平台或系统之间,通信必须满足两个条件,即端口和协议。
说白了,就是通信的窗口,和通信内容的格式。
只要封装Socket的时候,客户端和服务端采用相同的协议和端口即可通信。
至于通信内容的一致性就是另一码事了。
使用多线程,下面的代码,简单实现一个多线程的web服务器:
#coding=utf-8import socket
import threading
from time import sleep
def response(sock, addr):
print "收到请求"
data = sockrecv(1024)
print data
socksend(html)
sockclose()
html = '''HTTP/11 200 OK\nContent-Type: text/html\n\r\nHello world!'''
s = socketsocket(socketAF_INET, socketSOCK_STREAM)
sbind(('0000', 80))
slisten(50)
print "正在等待连接……"
while 1:
sleep(01)
sock,addr = saccept()
t = threadingThread(target=response, args=(sock,addr))
tstart()
第一层:应用层,定义了用于在网络中进行通信和传输数据的接口;(Http协议位于该层)
第二层:表示层,定义不同系统中数据的传输格式,编码和解码规范等;
第三层:会话层,管理用户的会话,控制用户间逻辑连接的建立和中断;
第四层:传输层,管理着网络中端到端的数据传输;(Tcp协议位于该层)
第五层:网络层,定义网络设备间如何传输数据;(IP位于该层)
第六层:链路层,将上面的网络层的数据包封装成数据帧,便于物理层传输;
第七层:物理层,这一层主要就是传输这些二进制数据。
建立起一个 TCP 连接需要经过“ 三次握手 ”:
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求。
SYN攻击就是利用三次握手的第二次握手时进行的,这时候服务器处于SYN_RECV状态,等待客户端进行确认ACK,SYN会伪造不存在的源IP,就会有大量的链接处于等待或重试发送SYN+ACK包,导致该阶段队列持续增长,进而导致后续正常请求被丢弃。
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”。
要保持客户端程序的在线状态,需要不断地向服务器发起连接请求,通常情况下即使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。
通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。
相关视频推荐
看完《tcp/ip详解》不能coding的,一次课开启设计tcp/ip协议栈
深入聊聊websocket协议,tcp分包与粘包解决方案
学习地址:C/C++Linux服务器开发/后台架构师零声教育-学习视频教程-腾讯课堂
需要C/C++ Linux服务器架构师学习资料加qun 812855908 获取(资料包括 C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg 等),免费分享
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
socket则是对TCP/IP协议的封装和应用(程序员层面上)。也可以说,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据。
关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:
平时说的最多的socket是什么呢,实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,才能使用TCP/IP协议。
实际上,Socket跟TCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,Socket的出现 只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了一些最基本的函数接口,比如create、 listen、connect、accept、send、read和write等等。
实际上,传输层 TCP 是基于网络层 IP 协议的,而应用层 HTTP 协议又是基于传输层 TCP 协议的,而 Socket 本身不算是协议,就像上面所说,它只是提供了一个针对 TCP 或者 UDP 编程的接口。
总结:
Socket 其实并不是一个协议,而是为了方便使用 TCP/UDP 而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。
当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
WebSocket就像HTTP一样,是一个典型的应用层协议。
总结:
WebSocket是HTML5规范提出的一种协议。HTML5 Web Sockets规范定义了Web Sockets API,支持页面使用Web Socket协议与远程主机进行全双工的通信。它引入了WebSocket接口并且定义了一个全双工的通信通道,通过一个单一的套接字在Web上进行操作。
HTML5 Web Sockets以最小的开销高效地提供了Web连接。相较于经常需要使用推送实时数据到客户端甚至通过维护两个HTTP连接来模拟全双工连接的旧的轮询或长轮询(Comet)来说,这就极大的减少了不必要的网络流量与延迟。
相同点:
不同点:
联系:
WebSocket连接的过程:
总结:
你可以在每个用户连上服务器端时,都发送一个消息,就是用4个字节表示是用户的ID,并将与用户通信的socket,用一个HashMap存储起来,而不是用LinkList。
后面如果A发送消息给C,就把A的前四个字节(即ID)取出来,在HashMap中找到与C通信的socket,然后把消息通过socket发送出去····
这部分代码应该很容易实现的,Socket通信这东西,理清了思路就很好弄了~~
Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便的编写网络上的数据的传递。在java中,有专门的socket类来处理用户的请求和响应。利用SOCKET类的方法,就可以实现两台计算机之间的通讯。这里就介绍一下在JAVA中如何利用socket进行网络编程。 在Java中Socket可以理解为客户端或者服务器端的一个特殊的对象,这个对象有两个关键的方法,一个是getInputStream方法,另一个是getOutputStream方法。getInputStream方法可以得到一个输入流,客户端的Socket对象上的getInputStream方法得到的输入流其实就是从服务器端发回的数据流。GetOutputStream方法得到一个输出流,客户端Socket对象上的getOutputStream方法返回的输出流就是将要发送到服务器端的数据流,(其实是一个缓冲区,暂时存储将要发送过去的数据)。 程序可以对这些数据流根据需要进行进一步的封装。本文的例子就对这些数据流进行了一定的封装(关于封装可以参考Java中流的实现部分)。 一、建立服务器类 Java中有一个专门用来建立Socket服务器的类,名叫ServerSocket,可以用服务器需要使用的端口号作为参数来创建服务器对象。ServerSocket server = new ServerS
感觉这样的提问没有什么意义
建议看看书,查查资料
0条评论