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;
}