#include <myhead.h>
#define SERPORT 5333
#define SERIP "192.168.0.118"
#define BACKLOG 10
#define MAX_CLIENTS 30
#define BUFFSIZE 1024
typedef struct {
struct sockaddr_in addr;
int cin_socket;
} Client;
int main(int argc, const char *argv[]) {
// 1. 创建套接字
int oldfd = socket(AF_INET, SOCK_STREAM, 0);
if (oldfd == -1) {
perror("socket");
return -1;
}
// 2. 端口号快速复用
int k = 1;
if (setsockopt(oldfd, SOL_SOCKET, SO_REUSEADDR, &k, sizeof(k)) == -1) {
perror("setsockopt");
return -1;
}
// 3. 填充结构体并绑定
struct sockaddr_in sin = {
.sin_family = AF_INET,
.sin_port = htons(SERPORT),
.sin_addr.s_addr = inet_addr(SERIP)
};
Client cin[MAX_CLIENTS];
struct sockaddr_in clinet;
int clinetlen = sizeof(clinet);
// 初始化客户端套接字数组
for (int i = 0; i < MAX_CLIENTS; i++) {
cin[i].cin_socket = 0;
}
if (bind(oldfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
perror("bind");
return -1;
}
printf("绑定成功\n");
// 4. 监听
if (listen(oldfd, BACKLOG) == -1) {
perror("listen");
return -1;
}
// 5. 读集合定义
fd_set readfds;
int maxfd;
int newfd;
// 6. 循环阻塞,选择接收或转发
while (1) {
// 清空读文件描述符集合
FD_ZERO(&readfds);
// 添加服务器套接字到集合中
FD_SET(oldfd, &readfds);
maxfd = oldfd;
// 添加客户端套接字到集合中
int sd;
for (int i = 0; i < MAX_CLIENTS; i++) {
sd = cin[i].cin_socket;
if (sd > 0) {
FD_SET(sd, &readfds);
}
if (sd > maxfd) {
maxfd = sd;
}
}
int res = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (res == 0) {
printf("timeout");
continue;
}
if (res == -1) {
perror("select");
continue;
}
if (FD_ISSET(oldfd, &readfds)) { // 接收客户端
newfd = accept(oldfd, (struct sockaddr *)&clinet, (socklen_t *)&clinetlen);
if (newfd == -1) {
perror("accept");
continue;
}
printf("%s:%d连接服务器成功\n", inet_ntoa(clinet.sin_addr), ntohs(clinet.sin_port));
// 添加新套接字到客户端套接字数组中
for (int i = 0; i < MAX_CLIENTS; i++) {
if (cin[i].cin_socket == 0) {
cin[i].cin_socket = newfd;
cin[i].addr = clinet;
printf("添加新套接字:%d\n", i+4);
break;
}
}
}
char buff[BUFFSIZE];
for (int i = 0; i < MAX_CLIENTS; i++) {
sd = cin[i].cin_socket;
if (FD_ISSET(sd, &readfds)) { // 收发事件
bzero(buff, sizeof(buff));
int len = read(sd, buff, sizeof(buff));
if (len == 0) {
printf("%s:%d断开了连接\n", inet_ntoa(cin[i].addr.sin_addr), ntohs(cin[i].addr.sin_port));
close(sd);
cin[i].cin_socket = 0;
} else { // 转发消息
printf("转发消息:%s\n", buff);
char message_with_info[BUFFSIZE + 50];
snprintf(message_with_info, sizeof(message_with_info), "%s:%d 说: %s",
inet_ntoa(cin[i].addr.sin_addr), ntohs(cin[i].addr.sin_port), buff);
for (int j = 0; j < MAX_CLIENTS; j++) {
if (cin[j].cin_socket != 0 && cin[j].cin_socket != sd) {
send(cin[j].cin_socket, message_with_info, strlen(message_with_info), 0);
printf("转发成功到 %d\n", cin[j].cin_socket);
}
}
}
}
}
}
close(oldfd);
return 0;
}
#include <myhead.h>
#include <poll.h>
#define SERPORT 8888
#define SERIP "192.168.0.120"
#define BUFFSIZE 1024
int main() {
// 1. 创建套接字
int oldfd = socket(AF_INET, SOCK_STREAM, 0);
if (oldfd == -1) {
perror("socket");
return -1;
}
// 2. 填充结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SERPORT);
sin.sin_addr.s_addr = inet_addr(SERIP);
// 3. 连接服务器
if (connect(oldfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
perror("connect");
return -1;
}
printf("连接服务器成功\n");
// 4. 创建poll
struct pollfd fds[2] = {{0, POLLIN}, {oldfd, POLLIN}};
// 5. 发消息
char buff[BUFFSIZE];
while (1) {
int res = poll(fds, 2, -1);
if (res == 0) {
printf("timeout\n");
return -1;
}
if (res == -1) {
perror("poll");
return -1;
}
if (fds[0].revents == POLLIN) {
fgets(buff, sizeof(buff), stdin);
buff[strlen(buff) - 1] = '\0';
if (write(oldfd, buff, strlen(buff)) == -1) {
perror("write");
return -1;
}
}
if (fds[1].revents & POLLIN) {
bzero(buff, sizeof(buff));
int len = recv(oldfd, buff, sizeof(buff), 0);
if (len == 0) {
printf("服务器断开连接\n");
break;
}
printf("%s\n", buff);
}
}
close(oldfd);
return 0;
}