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

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

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

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

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

Socket编程常用的函数

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

根据上面的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.youkuaiyun.com/chenlycly/article/details/51657179

ps: 欢迎关注我的公众号[酷酷的coder],分享转行菜鸟程序员成长过程汇总的烦恼和反思.

酷酷的Coder

### 如何转行成为程序员:学习路径技能要求 对于希望转行进入程序员行业的人员来说,明确的学习路径和必要的技能准备至关重要。以下是详细的指导: #### 1. **基础计算机科学知识** 编程的基础离不开扎实的计算机科学理论支持。建议从以下几个方面入手: - 数据结构算法:这是编程的核心部分之一,理解数据存储方式以及高效处理方法是至关重要的[^3]。 ```python def binary_search(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = (low + high) // 2 if arr[mid] == target: return mid elif arr[mid] < target: low = mid + 1 else: high = mid - 1 return -1 ``` - 计算机网络:了解HTTP协议、TCP/IP模型等内容有助于构建Web应用程序。 #### 2. **选择合适的编程语言** 初学者可以从易于入门的语言开始,逐步过渡到更复杂的工具和技术栈。 - Python:因其简洁易懂而被广泛用于教学环境及实际项目开发中[^4]。 - JavaScript/TypeScript:前端开发必备技能;随着Node.js的发展,在后端也有广泛应用场景。 #### 3. **实践驱动型学习模式** 实践是最好的老师。通过参开源项目或者自己动手实现小型应用来巩固所学到的知识点非常有效果[^1]。 #### 4. **持续关注行业动态发展潮流** 随着时间推移,新技术层出不穷。保持好奇心并不断更新自己的知识体系尤为重要。例如目前大火的人工智能领域中的深度学习框架TensorFlow,Keras等都是未来可探索的方向[^2]。 #### 5. **软实力培养同样不可忽视** 解决问题的能力、团队合作精神以及良好的沟通技巧都会影响一名优秀软件工程师的成长轨迹[^3]。 ```bash git clone https://github.com/example-repo.git cd example-repo npm install node app.js ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值