转行程序员浅谈进程间的 socket 通信

用户头像
WB
关注
发布于: 2020 年 05 月 31 日
转行程序员浅谈进程间的socket通信

我在之前的文章中曾说过,我现在开始负责车辆以太网应用层协议栈的开发和维护。



以太网通信说白了也属于计算机通信的范畴,因此网络通信的5层模型仍然适用于车辆通信领域。



既然设计到ECU间的网络通信,那么socket网络编程的知识一定是必不可少的。



今天这篇文章就总结我这周学习的socket网络编程的知识。



Socket编程常用的函数



首先,下图是client与server之间的通信流程图。





根据上面的socket通信流程图,socket编程常用的函数如下:

  • 客户端使用socket(), connect(), send(), recv(), close();

  • 服务端使用socket(), bind(), listen(), accept(), recv(), send(), close();



Socket通信的三次握手和四次挥手

Socket建立连接三次握手的流程
  • 第一次握手:client端先向server端发送连接请求

  • 第二次握手:server收到后,回复ACK给client

  • 第三次握手:client端收到ACK后,回复ACK给server

至此,client与server之间的网络连接建立,可以顺利进行数据传输。





Socket断开连接四次挥手的流程
  • 第一次挥手:client向server发送断开连接请求

  • 第二次挥手:server收到client的请求,回复ACK给client (这次挥手表示server收到了client的请求,但是并不会立即断开连接,可能还有未发送的数据)

  • 第三次挥手:server向client发送断开连接请求(这次挥手表示server端的数据已经发送完毕,client端可以断开)

  • 第四次挥手:client收到了server的请求,发送ACK给server。之后client端处于等待状态,过了一段时间后将socket关闭

至此,client与server之间的网络连接断开。



简单实现进程间的Socket的通信



实现步骤如下:

(1)使用socket套接字,并选择TCP/IP协议,端口号为6000

(2)客户端发送“this is a test”到服务端

(3)服务端收到后打印字符串,并回复“test ok”到客户端

(4)通信结束,断开连接



客户端socket通信的实现步骤
  • socket()创建socket

  • 设置socket的属性

  • connect()向服务端发起连接

  • send()向服务端发送消息

  • recv()等待服务端的消息

  • close()关闭socket,回收资源

//client.c
#include<stdio.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<netinet/in.h>
#define PORT 6000
int main()
{
int socketfd, error;
struct sockaddr_in serv_addr;
//创建socket
socketfd = socket(AF_INET, SOCK_STREAM, 0);
//设置socket的属性
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
//向服务端发起连接
error = connect(socketfd, &serv_addr, sizeof(struct sockaddr));
if(0 != error)
{
printf("connect server error.");
return 0;
}
//向服务端发送消息
char *buff = "this is a test";
error = send(socketfd, buff, strlen(buff), 0);
if(-1 == error)
{
printf("send message to server error.");
return 0;
}
//等待接收服务端的消息
char recv_buff[1024] = {0};
error = recv(socketfd, recv_buff, 1024,0);
if(-1 == error)
{
printf("receive error");
return 0;
}
printf("Receive buff:%s\n", recv_buff);
//关闭socket,回收资源
close(socketfd);
return 0;
}



服务端socket通信的实现步骤
  • socket()创建socket

  • bind()对socket进行绑定

  • listen()监听绑定的socket,用于监听来自客户端的消息

  • accept()用于接收客户端的连接请求和消息

  • recv()函数接收客户端的消息,并将其保存到设置好的buffer中

  • send()函数用于服务端向客户端发送消息

  • close()关闭socket,回收资源

//server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define PORT 6000
int main()
{
int socketfd, clientfd, error;
struct sockaddr_in server_addr, client_addr;
int sin_size;
char buff[1024] = {0};
//创建socket
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socketfd)
{
printf("create socket fail.");
return 0;
}
//socket属性设置
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
//绑定socket
error = bind(socketfd, &server_addr, sizeof(struct sockaddr_in));
if(0 != error)
{
printf("bind fail.");
close(socketfd);
return 0;
}
//监听socket
error = listen(socketfd, 5);
if(0 != error)
{
printf("listen fail.");
close(socketfd);
return 0;
}
//接收客户端的连接请求
clientfd = accept(socketfd, (struct sockaddr*)&client_addr, &sin_size);
//连接建立后,接收客户端的消息
error = recv(clientfd, buff, 1024,0);
if(-1 == error)
{
printf("receive error");
close(socketfd);
return 0;
}
printf("Receive buff:%s\n", buff);
//收到消息后,向客户端发送响应
char *send_buff = "test ok.";
error = send(clientfd, send_buff, strlen(send_buff), 0);
if(-1 == error)
{
printf("send error");
close(socketfd);
return 0;
}
//关闭socket,回收资源
close(socketfd);
return 0;
}



代码完成后,使用gcc编译代码,生成server和client的可执行文件。

然后,在linux界面打开两个命令行,先运行server进程,再运行client进程,即可观察到两个进程之间的通信。



总结



这篇文章承接的是之前《白话计算机网络》,但当时工作较忙一直没有更新。



此外,如果想继续学习socket通信和网络协议,推荐一个开源项目tinyhttp。该项目通过500行代码,利用多线程和socket通信简单实现了http协议,是很适合初学者学习的资源,强烈推荐!!!



我这两天正在阅读该项目的源码,等把项目源码吃透,会写一篇总结出来。



参考资料:

  • https://www.cnblogs.com/niwotaxuexiba/p/9700764.html

  • https://blog.csdn.net/chenlycly/article/details/51657179

发布于: 2020 年 05 月 31 日 阅读数: 38
用户头像

WB

关注

车联网,AutoSar,功能安全,Linux 2018.12.15 加入

还未添加个人简介

评论

发布
暂无评论
转行程序员浅谈进程间的socket通信