套接字(socket)是 Linux 下的一种进程间通信机制(socket IPC),它不仅支持同一主机的不同进程间通信,还支持跨网络的不同主机的进程间通信。
socket 允许通过标准的文件描述符进行网络数据传输,支持各种网络协议,如 TCP 和 UDP,它把复杂的 TCP/IP 协议隐藏在 socket 接口下,对用户来说,一组简单的接口就是全部,让 socket 去组织数据,以符合指定的协议。
基于 socket 接口编写的应用程序可以移植到任何实现 BSD socket 标准的平台。本文介绍了 Linux 下使用 socket 接口实现 TCP 客户端的示例程序。
- 开发环境:虚拟机 Ubuntu 18.04
- 验证平台:正点原子 Mini Linux 开发板
- 服务端:网络调试助手 NetAssist
示例代码
- tcp_client.c
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include "tcp_client.h"
int client_init_socket(void)
{
int socket_fd;
struct sockaddr_in server_address;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(SERVER_IP);
server_address.sin_port = htons(SERVER_PORT);
if (connect(socket_fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0)
{
perror("connect");
exit(EXIT_FAILURE);
}
return socket_fd;
}
int client_receive_data(int socket_fd, char *message, ssize_t *size)
{
ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0);
if (bytes_received == -1)
{
perror("recv");
exit(EXIT_FAILURE);
}
*size = bytes_received;
return 0;
}
void client_send_data(int socket_fd, const char *message, ssize_t size)
{
if (send(socket_fd, message, size, 0) < 0)
{
perror("send");
exit(EXIT_FAILURE);
}
}
int client_check_tcp_connection(int socket_fd)
{
int error = 0;
socklen_t len = sizeof(error);
if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0)
{
if (error == 0)
{
return 1;
}
}
return 0;
}
int client_close_socket(int socket_fd)
{
close(socket_fd);
return 0;
}
- tcp_client.h
c
#ifndef __TCP_CLIENT_H__
#define __TCP_CLIENT_H__
#include <sys/socket.h>
#define SERVER_IP "192.168.0.120"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024
int client_init_socket(void);
int client_receive_data(int socket_fd, char *message, ssize_t *size);
void client_send_data(int socket_fd, const char *message, ssize_t size);
int client_check_tcp_connection(int socket_fd);
int client_close_socket(int socket_fd);
#endif
- main.c
c
#include <stdio.h>
#include "tcp_client.h"
int main(void)
{
int client_fd = 0;
char buffer[1024] = {0};
ssize_t size = 0;
client_fd = client_init_socket();
client_send_data(client_fd, "Hello Server!", 13);
client_receive_data(client_fd, buffer, &size);
printf("%s \r\n", buffer);
client_close_socket(client_fd);
return 0;
}
板级验证
- 打开网络调试助手,设置为 TCP 服务端,选择本地主机地址和端口,点击打开:
- 代码中配置服务端 IP 与端口号,通过交叉编译生成目标程序,拷贝到 Elfboard Linux 开发板上:
c
#define SERVER_IP "192.168.221.1"
#define SERVER_PORT 8080
- 运行客户端程序
- 服务端显示客户端已连接,并接收到客户端消息:
- 服务端向客户端回复消息:
- 客户端接收到服务端消息: