这几天学习了linux环境下的socket 编程, 做了一些整理。
1. 代码如下:
/**
* @file socket_test.c
* @note
* @brief 网络C/S通信例程
* @author
* @date 2022/03/31
* @note :
* @note \n History:
1.Date : 2022/03/31
Author : LianXiang
Modification : 创建文件
*/
/* ========================================================================== */
/* 头文件 */
/* ========================================================================== */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
/* ========================================================================== */
/* 宏定义 */
/* ========================================================================== */
#define SERVER_IP "127.0.0.1" /* 根据不同的环境 修改SERVER_IP */
#define SERVER_PORT 5001
#define LISTEN_BACKLOG 50
#define handle_error(msg)\
do { perror(msg); exit(EXIT_FAILURE); } while (0)
/* ========================================================================== */
/* 函数声明 */
/* ========================================================================== */
void ServerProcess(void);
void ClientProcess(void);
/**
* main
* @brief 主函数
* @param[in] int argc
* @param[in] char *argv[]
* @param[out] void
* @return 0
*/
int main(int argc, char * argv[])
{
if (argc != 2) {
printf("Usage: %s client or server\n", argv[0]);
return - 1;
}
/* 根据执行的参数, 执行 client 或 server 进程 */
if (0 == memcmp(argv[1], "client", sizeof("client"))) {
ClientProcess();
} else if (0 == memcmp(argv[1], "server", sizeof("server"))) {
ServerProcess();
} else {
printf("Usage: %s client or server\n", argv[0]);
}
return 0;
}
/**
* ServerProcess
* @brief 服务器进程处理进程
* @param[in] void
* @param[out] void
* @return void
*/
void ServerProcess(void)
{
int serverSockfd = -1;
int acceptSockfd = -1;
socklen_t addrLen = 0;
char recvBuf[1024] = {0};
int recvLen = 0;
struct sockaddr_in tSocketServerAddr;
struct sockaddr_in tSocketClientAddr;
/* 调用 signal(SIGCHLD,SIG_IGN) 则子进程结束后,不再给父进程发送信号。
由内核负责回收,防止子进程变为僵尸进程 */
signal(SIGCHLD, SIG_IGN);
tSocketServerAddr.sin_family = AF_INET;
tSocketServerAddr.sin_port = htons(SERVER_PORT);
tSocketServerAddr.sin_addr.s_addr = htons(INADDR_ANY);
/* 1. 创建socket */
serverSockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == serverSockfd) {
handle_error("socket");
}
/* 2. 绑定socket */
if (-1 == bind(serverSockfd, (struct sockaddr *) &tSocketServerAddr, sizeof(struct sockaddr_in))) {
handle_error("bind");
}
/* 3. 监听 */
if (-1 == listen(serverSockfd, LISTEN_BACKLOG)) {
handle_error("listen");
}
while (1) {
addrLen = sizeof(struct sockaddr);
acceptSockfd = accept(serverSockfd, (struct sockaddr *) &tSocketClientAddr, &addrLen);
if (-1 != acceptSockfd) {
printf("Connected Client IP : %s \n", inet_ntoa(tSocketClientAddr.sin_addr));
printf("Waiting client send message...\n");
/* 创建子进程,用于多个client连接 */
if (0 == fork()) {
while (1) {
/* 阻塞接收客户端数据, 收到后返回,并打印 */
recvLen = recv(acceptSockfd, recvBuf, 1023, 0);
if (recvLen <= 0) {
close(acceptSockfd);
return;
} else {
recvBuf[recvLen] = '\0';
printf("Client: %s\n", recvBuf);
}
}
}
} else {
handle_error("accept");
}
}
close(serverSockfd);
serverSockfd = -1;
}
/**
* ClientProcess
* @brief 客户端进程处理进程
* @param[in] void
* @param[out] void
* @return void
*/
void ClientProcess(void)
{
int clientSockfd = -1;
struct sockaddr_in socketServerAddr;
char sendBuf[1024] = {0};
int sendLen = 0;
/* 1. 创建socket */
clientSockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == clientSockfd) {
handle_error("socket");
}
socketServerAddr.sin_family = AF_INET;
socketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */
/* 2. 转换server ip为网络字节序 */
if (0 == inet_aton(SERVER_IP, &socketServerAddr.sin_addr)) {
printf("Server ip error\n");
return;
}
/* 3. 连接server */
if (-1 == connect(clientSockfd, (const struct sockaddr *) &socketServerAddr, sizeof(struct sockaddr))) {
handle_error("connect");
} else {
printf("Connect success.\nPlease input message:\n");
}
/* 4. 循环输入内容,并发送给server */
while (1) {
if (fgets(sendBuf, 1023, stdin)) {
sendLen = send(clientSockfd, sendBuf, strlen(sendBuf), 0);
if (sendLen <= 0) {
close(clientSockfd);
return;
}
}
}
}
2. 运行步骤
1. 编译
gcc -o socket_test socket_test.c
2. 运行server端
./socket_test server
3. 运行client端
新开一个回话窗口,运行client
./socket_test client
4. client发送任意数据, server端可以显示
server端运行
client端运行