套接字(socket)是 linux 下的一种进程间通信机制(socket ipc),它不仅支持同一主机的不同进程间通信,还支持跨网络的不同主机的进程间通信。
socket 允许通过标准的文件描述符进行网络数据传输,支持各种网络协议,如 tcp 和 udp,它把复杂的 tcp/ip 协议隐藏在 socket 接口下,对用户来说,一组简单的接口就是全部,让 socket 去组织数据,以符合指定的协议。
基于 socket 接口编写的应用程序可以移植到任何实现 bsd socket 标准的平台。本文介绍了 linux 下使用 socket 接口实现 tcp 服务端的示例程序。
- 开发环境:虚拟机 ubuntu 18.04
- 验证平台:elfboard linux 开发板
- 客户端:windows 网络调试助手 netassist
示例代码
- tcp_server.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 <errno.h> #include "tcp_server.h" int server_init_socket(void) { int socket_fd; struct sockaddr_in address; if ((socket_fd = socket(af_inet, sock_stream, 0)) == 0) { perror("socket failed"); exit(exit_failure); } address.sin_family = af_inet; address.sin_addr.s_addr = inaddr_any; address.sin_port = htons(port); if (bind(socket_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(exit_failure); } if (listen(socket_fd, 3) < 0) { perror("listen"); exit(exit_failure); } return socket_fd; } int server_set_socket_timeout(int socket_fd, long milliseconds) { struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = (milliseconds % 1000) * 1000; if (setsockopt(socket_fd, sol_socket, so_rcvtimeo, (const char*)&tv, sizeof(tv)) < 0) { perror("setsockopt so_rcvtimeo"); exit(exit_failure); } return 0; } int server_accept_client(int socket_fd) { struct sockaddr_in address; int addrlen = sizeof(address); int temp_fd = accept(socket_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen); if (temp_fd < 0) { perror("accept"); exit(exit_failure); } printf("connection established with %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); return temp_fd; } int server_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) { if (errno == eagain || errno == ewouldblock || errno == etimedout) { printf("socket recv time out \r\n"); return 1; } else { perror("recv"); exit(exit_failure); } } *size = bytes_received; return 0; } void server_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 server_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 server_close_socket(int socket_fd) { close(socket_fd); return 0; }
- tcp_server.h
#ifndef __tcp_server__ #define __tcp_server__ #include <sys/socket.h> #define port 8080 #define buffer_size 1024 int server_init_socket(void); int server_accept_client(int socket_fd); int server_set_socket_timeout(int socket_fd, long milliseconds); int server_receive_data(int socket_fd, char *message, ssize_t *size) ; void server_send_data(int socket_fd, const char *message, ssize_t size); int server_check_tcp_connection(int socket_fd); int server_close_socket(int fd); #endif
- main.c
#include <stdio.h> #include "tcp_server.h" int main(void) { int server_fd, client_fd; char buffer[1024] = {0}; ssize_t size = 0; server_fd = server_init_socket(); client_fd = server_accept_client(server_fd); server_send_data(client_fd, "hello client!", 13); server_receive_data(client_fd, buffer, &size); printf("%s", buffer); server_close_socket(client_fd); server_close_socket(server_fd); return 0; }
- 通过交叉编译生成目标程序,拷贝到 elfboard linux 开发板上
板级验证
- 启动 elfboard linux 开发板作为服务端,查看 ip:
- 打开网络调试助手,配置协议类型为 tcp 客户端,设置服务端 ip、端口号:
- 运行服务端程序,等待客户端连接:
- 客户端点击连接:
- 服务端显示客户端已连接:
- 客户端收到服务端发送的消息:
- 客户端回复服务端消息:
- 服务端接收到客户端消息:
以上就是linux下使用使用socket实现tcp服务端的示例代码的详细内容,更多关于linux socket实现tcp服务端的资料请关注代码网其它相关文章!
发表评论