多线程并发TCP与UDP广播

1.TCP并发通信

说明:accept在没有接收到新的连接请求前会阻塞运行,并且因为传递给线程的参数是独立的client_sock,不必担心覆盖

#include <stdio.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 2345
#define MAX_CLIENTS 100

void *handle_client(void *socket_dest){
	int sock=*(int*)socket_dest;
	char buffer[1024];
	int read_size;

	//注意,当客户端发送数据长度为0或者关闭了连接都会返回0。
	while((read_size=recv(sock,buffer,1024,0))>0){
		printf("收到的消息%.*s\n",read_size,buffer);
		if(send(sock,buffer,read_size,0)<0){
			perror("发送失败");
			close(sock);
			free(socket_dest);
			return NULL;
		}
	}
	if(read_size==0){
		printf("客户端关闭");
	}else if(read_size==-1){
		perror("接收失败");
	}

	close(sock);
	free(socket_dest);
	return NULL;
}

int main(int argc, const char *argv[])
{
	int server_sock,client_sock,*new_sock;
	struct sockaddr_in server,client;
	socklen_t client_len=sizeof(client);

	if((server_sock=socket(AF_INET,SOCK_STREAM,0))==-1){
		perror("无法创建套接字");
		exit(EXIT_FAILURE);
	};
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=INADDR_ANY;
	server.sin_port=htons(PORT);

	if(bind(server_sock,(struct sockaddr*)&server,sizeof(server))<0){
		perror("绑定失败");
		close(server_sock);
		exit(EXIT_FAILURE);
	};

	if(listen(server_sock,MAX_CLIENTS)<0){
		perror("监听失败");
		close(server_sock);
		exit(EXIT_FAILURE);
	}

	printf("端口绑定成功");
	while((client_sock=accept(server_sock,(struct sockaddr*)&client,&client_len)))
	{
		if(client_sock<0){
			perror("连接失败");
			continue;
		}

		pthread_t client_thread;
		new_sock=malloc(sizeof(int));
		if(new_sock==NULL){
			perror("空间申请失败");
			close(client_sock);
			continue;
		};

		*new_sock=client_sock;
		if(pthread_create(&client_thread,NULL,handle_client,(void*)new_sock)<0){
			perror("创建线程失败");
			free(new_sock);
			close(client_sock);
		}

		pthread_detach(client_thread);
		
	}
	if(client_sock<0){
		perror("连接失败");
			close(server_sock);
	}
	close(server_sock);


	
	return 0;
}

2. UDP广播

需要注意的是:接收端和发送端的端口必须一致,这边同一个机器运行发送端和接收端,因此加了

SO_REUSEADDR允许当前端口被多个绑定。

服务端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BROADCAST_PORT 1245
#define BROADCAST_IP "255.255.255.255"
#define MESSAGE "Hello, Broadcast!"

int main(int argc, const char *argv[])
{
    int sock;
    struct sockaddr_in broadcast_addr;
    int broadcast_permission = 1;

    // 创建UDP套接字
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("套接字创建失败");
        exit(1);
    }

    // 设置套接字允许广播
    if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast_permission, sizeof(broadcast_permission)) < 0) {
        perror("设置广播权限失败");
        close(sock);
        exit(1);
    }

    // 设置广播地址和端口
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_port = htons(BROADCAST_PORT);
    broadcast_addr.sin_addr.s_addr = inet_addr(BROADCAST_IP);

    // 发送广播消息
    if (sendto(sock, MESSAGE, strlen(MESSAGE), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr)) < 0) {
        perror("广播发送失败");
        close(sock);
        exit(1);
    }

    printf("发送消息结束\n");
    close(sock);
    return 0;
}

客户端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BROADCAST_PORT 1245
#define BUFFER_SIZE 1024

int main(int argc, const char *argv[])
{
    int sock;
    struct sockaddr_in recv_addr;
    char buff[BUFFER_SIZE];
    socklen_t addr_len = sizeof(recv_addr);
    int reuse = 1;

    // 创建UDP套接字
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("套接字创建失败");
        exit(1);
    }

    // 设置SO_REUSEADDR选项,允许重复绑定端口
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
        perror("设置SO_REUSEADDR失败");
        close(sock);
        exit(1);
    }

    // 填充接收地址结构
    memset(&recv_addr, 0, sizeof(recv_addr));
    recv_addr.sin_family = AF_INET;
    recv_addr.sin_port = htons(BROADCAST_PORT);
    recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 绑定套接字到端口
    if (bind(sock, (struct sockaddr*)&recv_addr, sizeof(recv_addr)) < 0) {
        perror("绑定失败");
        close(sock);
        exit(1);
    }

    printf("等待广播消息...\n");

    // 接收广播消息
    while (1) {
        int recv_len = recvfrom(sock, buff, BUFFER_SIZE - 1, 0, (struct sockaddr*)&recv_addr, &addr_len);
        if (recv_len < 0) {
            perror("接收失败");
            close(sock);
            exit(1);
        }
        buff[recv_len] = '\0';  // Null-terminate the string
        printf("接收到的广播消息为: %s\n", buff);
    }

    close(sock);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值