118 lines
2.7 KiB
C
118 lines
2.7 KiB
C
// 群聊
|
|
#include <stdio.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <sys/types.h>
|
|
|
|
/*
|
|
* ./a.out port
|
|
*/
|
|
|
|
void *recv_task(void *arg);
|
|
void *send_task(void *arg);
|
|
|
|
int bind_port;
|
|
|
|
int main(int argc, char const *argv[])
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
printf("usage: %s port\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (sock_fd < 0)
|
|
{
|
|
perror("socket");
|
|
return EXIT_FAILURE; // 1
|
|
}
|
|
|
|
bind_port = atoi(argv[1]);
|
|
|
|
// 绑定端口
|
|
struct sockaddr_in bind_addr;
|
|
memset(&bind_addr, 0, sizeof(bind_addr));
|
|
bind_addr.sin_family = AF_INET;
|
|
bind_addr.sin_port = htons(bind_port);
|
|
bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
bind(sock_fd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); // 绑定文件描述符和地址端口
|
|
|
|
// 设置 socket 选项为广播
|
|
int val = 1;
|
|
int ret = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
|
|
if (ret != 0)
|
|
{
|
|
perror("setsockopt");
|
|
}
|
|
|
|
pthread_t tid1, tid2;
|
|
pthread_create(&tid1, NULL, recv_task, &sock_fd);
|
|
pthread_create(&tid2, NULL, send_task, &sock_fd);
|
|
|
|
pthread_join(tid2, NULL);
|
|
pthread_cancel(tid1);
|
|
pthread_join(tid1, NULL);
|
|
|
|
printf("---over---\n");
|
|
close(sock_fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *recv_task(void *arg)
|
|
{
|
|
int sock_fd = *((int *)arg);
|
|
|
|
while (1)
|
|
{
|
|
struct sockaddr_in data_addr;
|
|
socklen_t data_addr_len = sizeof(data_addr);
|
|
bzero(&data_addr, data_addr_len);
|
|
|
|
char buf[128] = "";
|
|
|
|
ssize_t recv_len = recvfrom(sock_fd, buf, 128, 0, (struct sockaddr *)&data_addr, &data_addr_len);
|
|
if (recv_len > 0)
|
|
{
|
|
char ip[16] = "";
|
|
inet_ntop(AF_INET, &data_addr.sin_addr.s_addr, ip, 16);
|
|
printf("%s(%d): %s\n", ip, ntohs(data_addr.sin_port), buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
void *send_task(void *arg)
|
|
{
|
|
int sock_fd = *((int *)arg);
|
|
|
|
while (1)
|
|
{
|
|
char buf[128] = "";
|
|
if (fgets(buf, 128, stdin) != NULL)
|
|
{
|
|
buf[strlen(buf) - 1] = 0;
|
|
|
|
struct sockaddr_in addr;
|
|
bzero(&addr, sizeof(addr));
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(bind_port);
|
|
addr.sin_addr.s_addr = inet_addr("10.35.188.255"); // 一定是广播地址
|
|
|
|
sendto(sock_fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&addr, sizeof(addr));
|
|
if (strncmp(buf, "bye", 3) == 0)
|
|
{
|
|
break;
|
|
}
|
|
if (strncmp(buf, "clear", 5) == 0)
|
|
{
|
|
system("clear");
|
|
}
|
|
}
|
|
}
|
|
} |