今日任务
对于newfd的话,最好是另存然后传入给分支线程,避免父子线程操作同一个文件描述符
------------在tcp多线程服务端----------
如果使用全局变量,或者指针方式间接访问,会导致所有线程共用一份newfd和cin,那么newfd和cin会被覆盖
代码:
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.255"
#define PORT 8888
/*
* function: 广播,接收方
* @param [ in]
* @param [out]
* @return
*/
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket success");
//绑定IIF(P和端口号(广播ip)
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(IP);
socklen_t addrlen=sizeof(addr);
if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
ERR_MSG("bind");
}
puts("bind success");
//存储发送方地址消息
struct sockaddr_in source_addr;
socklen_t source_addrlen=sizeof(source_addr);
//循环接受消息
char buf[128]="";
while(1){
bzero(buf,sizeof(buf));
int recv_res=recvfrom(sfd,&buf,sizeof(buf),0,(struct sockaddr*)&source_addr,&source_addrlen);
if(recv_res<0){
ERR_MSG("recvfrom");
return -1;
}
puts("recvfrom success");
printf("[%s:%d]:%s\n",inet_ntoa(source_addr.sin_addr),ntohs(source_addr.sin_port),buf);
}
//关闭
close(sfd);
return 0;
}
代码:
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.255"
#define PORT 8888
/*
* function: 广播,发送方
* @param [ in]
* @param [out]
* @return
*/
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket success");
//设置允许广播
int optval=1;//非0为允许
socklen_t optlen=sizeof(optval);
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&optval,optlen)<0){
ERR_MSG("setsockopt");
return -1;
}
//IP和端口号(广播ip)
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(IP);
socklen_t addrlen=sizeof(addr);
//循环发送消息
char buf[128]="";
while(1){
bzero(buf,sizeof(buf));
printf("请输入>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,addrlen)<0){
ERR_MSG("sendto");
return -1;
}
puts("sendto success");
}
//关闭
close(sfd);
return 0;
}
代码:
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.2"
#define PORT 8888
#define GRP_IP "224.1.2.3"
/*
* function: 组播:接收方
* @param [ in]
* @param [out]
* @return
*/
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket success");
//加入多播组
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr(GRP_IP); //组播IP
mq.imr_address.s_addr = inet_addr(IP); //本机IP,ifconfig
mq.imr_ifindex = 2; //网络设备索引号
if(setsockopt(sfd,IPPROTO_IP, IP_ADD_MEMBERSHIP,&mq,sizeof(mq))<0){
ERR_MSG("setsockopt");
return -1;
}
//绑定IIF(P和端口号(广播ip)
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(GRP_IP);
socklen_t addrlen=sizeof(addr);
if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
ERR_MSG("bind");
}
puts("bind success");
//接受对方地址信息
struct sockaddr_in source_addr;
socklen_t source_addrlen=sizeof(source_addr);
char buf[128]="";
while(1){
//接收消息
bzero(buf,sizeof(buf));
int recv_res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&source_addr, &source_addrlen);
if(recv_res < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s:%d] : %s\n", \
inet_ntoa(source_addr.sin_addr), ntohs(source_addr.sin_port), buf);
}
//关闭
close(sfd);
return 0;
}
代码
#include
#include
#include
#include
#include
#include
#include
#define ERR_MSG(msg) do{\
perror(msg);\
fprintf(stderr,"__%d__",__LINE__);\
}while(0)
#define IP "192.168.125.2"
#define PORT 8888
#define GRP_IP "224.1.2.3"
/*
* function: 组播:发送方
* @param [ in]
* @param [out]
* @return
*/
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket success");
//绑定IIF(P和端口号(广播ip)
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(GRP_IP);
socklen_t addrlen=sizeof(addr);
if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
ERR_MSG("bind");
}
puts("bind success");
char buf[128]="";
while(1){
//发送消息
bzero(buf,sizeof(buf));
printf("请输入>>> ");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = 0;
//发送数据, 主动发送给指定接收放,例如这里可以主动发给接收方
if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");
}
//关闭
close(sfd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
//自定义报错提示
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define SER_PORT 8888
#define SER_IP "192.168.125.2"
/*
* function: TCP服务端
* @param [ in]
* @param [out]
* @return
*/
int recv_send(int cfd,struct sockaddr_in cli_addr);
void handle(int sig){
while(waitpid(-1,NULL,WNOHANG)>0);
return ;
}
int main(int argc, const char *argv[])
{
//监听回收僵尸进程
if(signal(SIGCHLD,handle)==SIG_ERR){
ERR_MSG("signal");
return -1;
}
//1.创建socket套接字,
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket create");
//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速复用成功\n");
//2.绑定服务器IP和端口号bind
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(SER_PORT);
addr.sin_addr.s_addr=inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
ERR_MSG("bind");
return -1;
}
puts("bind success");
//3.建立监听listen
if(listen(sfd,128)<0){
ERR_MSG("listen");
return -1;
}
puts("listen suucess");
//4.等待客户端连接, accept
struct sockaddr_in cli_addr;
socklen_t cli_addrlen=sizeof(cli_addr);
pid_t pid;
while(1){
int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
if(cfd<0){
ERR_MSG("accept");
return -1;
}
puts("accept");
pid=fork();
if(pid==0){
//子进程执行信息收发
recv_send(cfd,cli_addr);
exit(0);
}else if(pid<0){
ERR_MSG("fork");
return -1;
}
close(cfd);
}
//6.关闭
close(sfd);
return 0;
}
int recv_send(int cfd,struct sockaddr_in cli_addr){
//5.接受发送消息recv;send
char buf[128];
while(1){
bzero(buf,sizeof(buf));
int recv_res=recv(cfd,buf,sizeof(buf),0);
if(recv_res<0){
ERR_MSG("recv");
return -1;
}else if(recv_res==0){
printf("socket peer has shutdown\n");
break;
}
puts("recv success");
printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
if(strcmp(buf,"quit")==0)
break;
strcat(buf,"-----i has received");
int send_res=send(cfd,buf,sizeof(buf),0);
if(send_res<0){
ERR_MSG("send");
return -1;
}
puts("send success");
}
}
代码:
#include
#include
#include
#include
#include
#include
#include
#include
//自定义报错提示
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
#define SER_PORT 8888
#define SER_IP "192.168.125.2"
struct cliMsg{
int cfd;
struct sockaddr_in cli_addr;
};
/*
* function: TCP服务端
* @param [ in]
* @param [out]
* @return
*/
void* recv_send(void*arg);
int main(int argc, const char *argv[])
{
//1.创建socket套接字,
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0){
ERR_MSG("socket");
return -1;
}
puts("socket create");
//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速复用成功\n");
//2.绑定服务器IP和端口号bind
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(SER_PORT);
addr.sin_addr.s_addr=inet_addr(SER_IP);
if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
ERR_MSG("bind");
return -1;
}
puts("bind success");
//3.建立监听listen
if(listen(sfd,128)<0){
ERR_MSG("listen");
return -1;
}
puts("listen suucess");
//4.等待客户端连接, accept
struct sockaddr_in cli_addr;
socklen_t cli_addrlen=sizeof(cli_addr);
pthread_t pth;
while(1){
int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
if(cfd<0){
ERR_MSG("accept");
return -1;
}
puts("accept");
struct cliMsg climsg;
climsg.cfd=cfd;
climsg.cli_addr=cli_addr;
//创建调用线程执行
if(pthread_create(&pth,NULL,recv_send,(void *)&climsg)!=0){
fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
return -1;
}
pthread_detach(pth);
}
close(sfd);
return 0;
}
void* recv_send(void*arg){
//5.接受发送消息recv;send
int cfd=((struct cliMsg*)arg)->cfd;
struct sockaddr_in cli_addr=((struct cliMsg*)arg)->cli_addr;
char buf[128];
while(1){
bzero(buf,sizeof(buf));
int recv_res=recv(cfd,buf,sizeof(buf),0);
if(recv_res<0){
ERR_MSG("recv");
break;
}else if(recv_res==0){
printf("socket peer has shutdown\n");
break;
}
puts("recv success");
printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
if(strcmp(buf,"quit")==0)
break;
strcat(buf,"-----i has received");
int send_res=send(cfd,buf,sizeof(buf),0);
if(send_res<0){
ERR_MSG("send");
break;
}
puts("send success");
}
close(cfd);
pthread_exit(NULL);
}
今日思维导图
不知道最近确实是脑子比较慢,还是拖拉,做事太慢了,tcp的代码还没复敲;