目录
- socket 编程接口
- TCP 服务端
- TCP 客户端
- 更多内容
本文介绍了 Linux 下的 socket 编程,及总结了使用 socket 接口实现 TCP 服务端和客户端的示例代码。
socket 编程接口
- socket() 函数:用于创建一个新的 socket 描述符:
int socket(int domain, int type, int protocol);
其中,domain 指定协议族(如 AF_INET 表示 IPv4),type 指定 socket 类型(如 SOCK_STREAM 表示 TCP,SOCK_DGRAM 表示 UDP),protocol 通常设置为 0,表示使用默认协议。
- bind() 函数:将 socket 绑定到一个 IP 地址或端口上:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指针,包含了 IP 地址和端口号信息,addrlen 是 struct sockaddr 的大小。
- listen() 函数:用于监听一个 socket 上的连接请求:
int listen(int sockfd, int backlog);
其中,sockfd 是 socket 描述符,backlog 指定了等待连接的最大队列长度。
- accept() 函数:从监听 socket 的等待队列中接受一个连接:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
该函数返回一个新的 socket 描述符,用于与客户端进行通信,addr 和 addrlen 用于获取客户端的地址信息。
- connect() 函数:用于建立一个到服务器的连接:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
其中,sockfd 是 socket 描述符,addr 是指向 struct sockaddr 的指针,包含了服务器的 IP 地址和端口号信息。
- send() 和 recv() 函数:用于通过 socket 发送和接收数据:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
其中,sockfd 是 socket 描述符,buf 是指向数据缓冲区的指针,len 是缓冲区的大小,flags 是控制函数行为的标志。
- close() 函数:用于关闭一个 socket:
int close(int sockfd);
其中,sockfd 是 socket 描述符。
- 在 Linux 下进行 socket 编程时,通常还需要处理错误和异常情况,以及进行地址转换(使用 inet_ntop 和 inet_pton 函数)和字节序转换(使用 htons 和 ntohs 函数)等操作。
TCP 服务端
- 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 <sys/time.h>
#include <errno.h>
#include "tcp_server.h"char buffer[BUFFER_SIZE] = {0};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 1024extern char buffer[BUFFER_SIZE];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 recv_buffer[1024];ssize_t size = 0;server_fd = server_init_socket();client_fd = server_accept_client(server_fd);server_send_data(client_fd, "Hello TCP!", 10);server_receive_data(client_fd, recv_buffer, &size);printf("%s", recv_buffer);return 0;
}
TCP 客户端
- tcp_client.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
#ifndef __TCP_CLIENT_H__
#define __TCP_CLIENT_H__#include <sys/socket.h>#define SERVER_IP "192.168.0.123"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int 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
#include <stdio.h>
#include "tcp_client.h"int main(void)
{int client_fd = 0;char buffer[1024];ssize_t size = 0;client_fd = client_init_socket();client_send_data(client_fd, "Hello TCP!", 10);client_receive_data(client_fd, buffer, &size);printf("%s", recv_buffer);return 0;
}
更多内容
- CSDN博客:@Hello阿尔法
- 哔哩哔哩:@Hello阿尔法
- 知乎:@Hello阿尔法