服务端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <signal.h>
#include <arpa/inet.h>
#define PORT "10000"
#define BUFFER_SIZE 1024
#define TRUE 1
#define FALSE 0
// 错误处理
void error_handler(const char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
// 子进程处理
void child_handler(int sig) {
if (sig == SIGCHLD) {
int state;
pid_t pid = waitpid(-1, &state, WNOHANG);
if (WIFEXITED(state)) {
printf("Child %d process end, return %d\n", pid, WEXITSTATUS(state));
}
}
}
int main() {
int server_sock;
server_sock = socket(PF_INET, SOCK_STREAM, 0);
if (server_sock == -1) {
error_handler("socket() error");
}
// 消除Timewait时间不可分配地址
int option = TRUE;
int op_len = sizeof(option);
setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&option, op_len);
// 发送缓存设置
int send_buffer = BUFFER_SIZE;
op_len = sizeof(send_buffer);
setsockopt(server_sock, SOL_SOCKET, SO_SNDBUF, (void *)&send_buffer, op_len);
// 接收缓存设置
int receive_buffer = BUFFER_SIZE;
op_len = sizeof(receive_buffer);
setsockopt(server_sock, SOL_SOCKET, SO_RCVBUF, (void *)&receive_buffer, op_len);
// 子进程处理
struct sigaction act;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
act.sa_handler = child_handler;
sigaction(SIGCHLD, &act, 0);
// 地址初始化
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(atoi(PORT));
if (bind(server_sock, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
error_handler("bind() error");
}
if (listen(server_sock, 1024) == -1) {
error_handler("listen() error");
}
int client_sock;
struct sockaddr_in client_address;
socklen_t client_address_len = sizeof(client_address);
while (1) {
client_sock = accept(server_sock, (struct sockaddr *)&client_address, &client_address_len);
if (client_sock == -1) {
continue;
} else {
puts("new connect...");
}
pid_t pid = fork();
if (pid == 0) {
// 子进程逻辑
close(server_sock);
char buffer[BUFFER_SIZE];
FILE *write_fp = fdopen(client_sock, "w");
FILE *read_fp = fdopen(dup(client_sock), "r");
while (1) {
if (fgets(buffer, BUFFER_SIZE - 1, read_fp) == NULL) {
break;
}
fputs(buffer, write_fp);
fflush(write_fp);
}
char str[] = "Thank you!";
fputs(str, write_fp);
fflush(write_fp);
fclose(write_fp);
fclose(read_fp);
return 0;
} else {
// 父进程逻辑
close(client_sock);
continue;
}
}
return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define IP "127.0.0.1"
#define PORT "10000"
#define BUFFER_SIZE 1024
void error_handler(const char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main() {
int sock;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
error_handler("socket() error");
}
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(IP);
address.sin_port = htons(atoi(PORT));
if (connect(sock, (struct sockaddr *)&address, sizeof(address)) == -1) {
error_handler("connect() error");
}
char message[BUFFER_SIZE];
FILE *read_fp = fdopen(sock, "r");
FILE *write_fp = fdopen(dup(sock), "w");
while (1) {
fputs("Input Message: ", stdout);
fgets(message, BUFFER_SIZE, stdin);
if (!strcmp(message, "Q\n") || !strcmp(message, "q\n")) {
shutdown(fileno(write_fp), SHUT_WR);
fclose(write_fp);
break;
}
fputs(message, write_fp);
fflush(write_fp);
fgets(message, BUFFER_SIZE, read_fp);
printf("Message from server: %s\n", message);
}
fgets(message, BUFFER_SIZE, read_fp);
printf("last Message from server: %s\n", message);
fclose(read_fp);
return 0;
}