广播
#include <myhead.h>
#define ERR_MSG(msg) do{\
printf("__%d__\n",__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.123.255"
#define PORT 6666
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sfd = %d\n",sfd);
//填充接收方地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//绑定接收方的地址信息,IP和端口号
if (bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//创建发送方地址信息结构体
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//定义容器
char buf[128] = "";
while (1)
{
bzero(buf,sizeof(buf));
//接收数据
if (recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)&cin,&addrlen) < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s : %d] : %s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
}
//关闭套接字
close(sfd);
return 0;
}
#include <myhead.h>
#define ERR_MSG(msg) do{\
printf("__%d__\n",__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.123.255"
#define PORT 6666
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("cfd = %d\n",cfd);
//设置允许广播
int broad = 1;
if (setsockopt(cfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("广播设置成功\n");
//填充接收方的地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//定义容器
char buf[128] = "";
while (1)
{
bzero(buf,sizeof(buf));
//发送数据
printf("请输入:");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
if (sendto(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("send success\n");
}
//关闭套接字
close(cfd);
return 0;
}
组播
#include <myhead.h>
#define ERR_MSG(msg) do{\
printf("__%d__\n",__LINE__);\
perror(msg);\
}while(0)
#define GRP_IP "224.1.2.3"
#define LOL_IP "192.168.123.126"
#define PORT 6666
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sfd = %d\n",sfd);
//加入多播组
//创建多播组结构体
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr(GRP_IP);
mq.imr_address.s_addr = inet_addr(LOL_IP);
mq.imr_ifindex = 0;
if (setsockopt(sfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mq,sizeof(mq)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("加入组播成功\n");
//填充接收方地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(GRP_IP);
//绑定接收方的地址信息,IP和端口号
if (bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//创建发送方地址信息结构体
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//定义容器
char buf[128] = "";
while (1)
{
bzero(buf,sizeof(buf));
//接收数据
if (recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)&cin,&addrlen) < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s : %d] : %s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
}
//关闭套接字
close(sfd);
return 0;
}
#include <myhead.h>
#define ERR_MSG(msg) do{\
printf("__%d__\n",__LINE__);\
perror(msg);\
}while(0)
#define IP "224.1.2.3"
#define PORT 6666
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("cfd = %d\n",cfd);
//填充接收方的地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//定义容器
char buf[128] = "";
while (1)
{
bzero(buf,sizeof(buf));
//发送数据
printf("请输入:");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
if (sendto(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("send success\n");
}
//关闭套接字
close(cfd);
return 0;
}
TCP多进程并发服务器
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.123.126"
#define PORT 6666
int del_cli_msg(int newfd,struct sockaddr_in cin);
void handler(int singno)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
int main(int argc, const char *argv[])
{
//捕获17号信号
if (signal(SIGCHLD,handler) == SIG_ERR)
{
ERR_MSG("signal");
return -1;
}
printf("捕获17号信号成功\n");
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速被使用
int reuse = 1;
if (setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速重用成功\n");
//填充服务器信息结构体给bind用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//绑定服务器IP和端口
if (bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//将套接字设置为被动监听状态
if (listen(sfd,128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//存储客户端地址信息
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
int newfd = -1;
pid_t cpid = 0;
while (1)
{
//生成新的文件描述符从已完成连接的队列头中获取一个客户端信息
newfd = accept(sfd,(struct sockaddr *)&cin,&addrlen);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s : %d] newfd = %d客户端连接成功\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//已连接成功,创建子进程用于收发数据
cpid = fork();
if (0 == cpid)
{
close(sfd);
del_cli_msg(newfd,cin);
close(newfd);
exit(EXIT_SUCCESS);
}
close(newfd);
}
//关闭文件描述符
if (close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}
int del_cli_msg(int newfd,struct sockaddr_in cin)
{
//定义容器
char buf[128] = "";
ssize_t res = 0;
while (1)
{
bzero(buf,sizeof(buf));
//接收数据
res = recv(newfd,buf,sizeof(buf),0);
if (res < 0)
{
ERR_MSG("recv");
return -1;
}
else if (0 == res)
{
printf("[%s : %d] newfd = %d 客户端下线\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
break;
}
printf("[%s : %d] newfd = %d : %s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf);
//发送数据
strcat(buf,"*_*");
if (send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
printf("send success\n");
}
return 0;
}
TCP多线程并发服务器
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.123.126"
#define PORT 6666
struct cliinfo
{
int newfd;
struct sockaddr_in cin;
};
void *del_cli_msg(void *arg);
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速被使用
int reuse = 1;
if (setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速重用成功\n");
//填充服务器信息结构体给bind用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//绑定服务器IP和端口
if (bind(sfd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success\n");
//将套接字设置为被动监听状态
if (listen(sfd,128) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//存储客户端地址信息
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
int newfd = -1;
pthread_t tid;
struct cliinfo msg;
while (1)
{
//生成新的文件描述符从已完成连接的队列头中获取一个客户端信息
newfd = accept(sfd,(struct sockaddr *)&cin,&addrlen);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s : %d] newfd = %d客户端连接成功\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
msg.newfd = newfd;
msg.cin = cin;
//已连接成功,创建分支程用于收发数据
if (pthread_create(&tid,NULL,del_cli_msg,(void *)&msg) != 0)
{
fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
return -1;
}
//分离线程,退出后内核自动回收线程
pthread_detach(tid);
}
//关闭文件描述符
if (close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}
void *del_cli_msg(void *arg)
{
int newfd = ((struct cliinfo *)arg)->newfd;
struct sockaddr_in cin = ((struct cliinfo *)arg)->cin;
//定义容器
char buf[128] = "";
ssize_t res = 0;
while (1)
{
bzero(buf,sizeof(buf));
//接收数据
res = recv(newfd,buf,sizeof(buf),0);
if (res < 0)
{
ERR_MSG("recv");
break;
}
else if (0 == res)
{
printf("[%s : %d] newfd = %d 客户端下线\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
break;
}
printf("[%s : %d] newfd = %d : %s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf);
//发送数据
strcat(buf,"*_*");
if (send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
break;
}
printf("send success\n");
}
close(newfd);
pthread_exit(NULL);
}
全局变量定义newfd后,同属一个进程下的线程共享全局变量,每有一个新的进程创建,将全局变量newfd数值改变,不会再创建新的newfd