/*TCP并发服务器端*/
#include <myhead.h>
#define SER_IP "192.168.125.173"
#define SER_PORT 8888
void sighanger(int signum){if(signum==SIGCHLD){//子进程终止信号while(waitpid(-1,NULL,WNOHANG)>0);//循环回收僵尸进程}
}int main(int argc, const char *argv[])
{//函数调用出错返回SIG_ERRif(signal(SIGCHLD,sighanger)==SIG_ERR){perror("signal error");return -1;}//创建套接字int rfd=socket(AF_INET,SOCK_STREAM,0);if(rfd==-1){perror("socket error");return -1;}printf("socket success\n");//为服务器绑定ip地址端口号struct sockaddr_in cin;cin.sin_family=AF_INET;cin.sin_port=htons(SER_PORT);cin.sin_addr.s_addr=inet_addr(SER_IP);if(bind(rfd,(struct sockaddr*)&cin,sizeof(cin))==-1){perror("bind error");return -1;}//设置监听if(listen(rfd,128)==-1){perror("listen error");return -1;}printf("listen success\n");struct sockaddr_in sin;socklen_t socklen=sizeof(sin);while(1){//循环接收客户端请求int newfd=accept(rfd,(struct sockaddr*)&sin,&socklen);if(newfd==-1){perror("accept error");return -1;}pid_t pid=fork();if(pid>0){close(newfd);}else if(pid==0){//子进程数据通信close(rfd);char rbuf[128]="";while(1){bzero(rbuf,sizeof(rbuf));int res=read(newfd,rbuf,sizeof(rbuf));if(res==0){printf("客户端已下线\n");break;}printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);//将字符串加777发送回去strcat(rbuf,"777");write(newfd,rbuf,sizeof(rbuf));printf("发送成功\n");}close(newfd);exit(EXIT_SUCCESS);}}close(rfd);return 0;
}
//多线程实现TCP并发服务器
#include<myhead.h>
#define SER_IP "192.168.125.117" //服务器IP地址
#define SER_PORT 8888 //服务器端口号//定义用于给线程体传参的结构体类型
struct MsgInfo
{int newfd;struct sockaddr_in cin;
};//定义线程体函数
void *deal_cli_msg(void *arg)
{//将传递进来的数据解析出来int newfd = ((struct MsgInfo*)arg)->newfd;struct sockaddr_in cin = ((struct MsgInfo*)arg)->cin;//5、数据通信char rbuf[128] = ""; //用于接受消息while(1){bzero(rbuf, sizeof(rbuf)); //清空容器//从套接字文件中读取消息//int ret = read(newfd, rbuf, sizeof(rbuf));int ret = recv(newfd, rbuf, sizeof(rbuf), 0);if(ret == 0){printf("客户端已下线\n");break;}printf("[%s:%d]: %s\n", \inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),rbuf );//将字符串加个笑脸回回去strcat(rbuf, "*_*");//write(newfd, rbuf, strlen(rbuf));send(newfd, rbuf, strlen(rbuf), 0);printf("发送成功\n");}//6、关闭套接字close(newfd);//退出线程pthread_exit(NULL);}/**主程序**/
int main(int argc, const char *argv[])
{//1、创建套节字:用于接收客户端链接请求的int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd == -1){perror("socket error");return -1;}printf("socket success sfd = %d\n", sfd); //3//设置端口号快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、绑定IP地址和端口号//2.1 填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //地址族sin.sin_port = htons(SER_PORT); //端口号sin.sin_addr.s_addr = inet_addr(SER_IP); //IP地址//2.2 绑定工作if( bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) ==-1){perror("bind error");return -1;}printf("bind success\n");//3、讲套节字设置成被动监听状态if( listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success\n");//4、阻塞等待客户端连接请求//定义地址信息结构体变量用于接受客户端的地址信息struct sockaddr_in cin;socklen_t socklen = sizeof(cin); //接受地址信息的长度while(1){int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);if(newfd == -1){perror("accept error");return -1;}printf("[%s:%d]:已连接, newfd = %d\n",\inet_ntoa(cin.sin_addr), ntohs(cin.sin_port) ,newfd); //4//定义用于传参的变量struct MsgInfo info = {newfd, cin};//创建分支线程用于通信pthread_t tid = -1;if(pthread_create(&tid, NULL, deal_cli_msg, &info) != 0){printf("线程创建失败\n");return -1;}//回收分支线程的资源pthread_detach(tid);}close(sfd);return 0;
}
//流式域套接字服务器端
#include<myhead.h>
int main(int argc, const char *argv[])
{//1、创建套节字:用于接收客户端链接请求的int sfd = socket(AF_UNIX, SOCK_STREAM, 0);if(sfd == -1){perror("socket error");return -1;}printf("socket success sfd = %d\n", sfd); //3//判断要绑定的套接字文件是否存在,如果存在,需要将其删除if(access("./unix", F_OK) == 0){//说明文件存在,需要将其删除if(unlink("./unix") != 0){perror("unlink error");return -1;}}//2、绑定套接字文件//2.1 填充地址信息结构体struct sockaddr_un sun;sun.sun_family = AF_UNIX; //通信域strcpy(sun.sun_path , "./unix"); //套接字文件//2.2 绑定工作if( bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) ==-1){perror("bind error");return -1;}printf("bind success\n");//3、讲套节字设置成被动监听状态if( listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success\n");//4、阻塞等待客户端连接请求//定义地址信息结构体变量用于接受客户端的地址信息struct sockaddr_un cun;socklen_t socklen = sizeof(cun); //接受地址信息的长度int newfd = accept(sfd, (struct sockaddr*)&cun, &socklen);if(newfd == -1){perror("accept error");return -1;}printf("[%s]:已连接, newfd = %d\n", cun.sun_path,newfd); //4//5、数据通信char rbuf[128] = ""; //用于接受消息while(1){bzero(rbuf, sizeof(rbuf)); //清空容器//从套接字文件中读取消息//int ret = read(newfd, rbuf, sizeof(rbuf));int ret = recv(newfd, rbuf, sizeof(rbuf), 0);if(ret == 0){printf("客户端已下线\n");break;}printf("[%s]: %s\n", cun.sun_path ,rbuf );//将字符串加个笑脸回回去strcat(rbuf, "*_*");//write(newfd, rbuf, strlen(rbuf));send(newfd, rbuf, strlen(rbuf), 0);printf("发送成功\n");}//6、关闭套接字close(newfd);close(sfd);return 0;
}
//报式域套接字服务器端
#include<myhead.h>
int main(int argc, const char *argv[])
{//1、创建用于通信的套接字文件描述符int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);if(sfd == -1){perror("socket error");return -1;}printf("socket success sfd = %d\n", sfd); //3//判断要绑定的套接字文件是否存在,如果存在,需要将其删除if(access("./unix", F_OK) == 0){//说明文件存在,需要将其删除if(unlink("./unix") != 0){perror("unlink error");return -1;}}//2、绑定IP地址和端口号//2.1 填充地址信息结构体struct sockaddr_un sun;sun.sun_family = AF_UNIX; //协议族strcpy(sun.sun_path, "./unix"); //服务器的套接字文件//2.2 绑定工作if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) == -1){perror("bind error");return -1;}printf("bind success\n");//3、数据的收发//定义变量接收客户端地址信息结构体struct sockaddr_un cun;socklen_t socklen = sizeof(cun);char rbuf[128] = "";while(1){bzero(rbuf, sizeof(rbuf));//读取套接字中的数据recvfrom(sfd, rbuf, sizeof(rbuf), 0, (struct sockaddr*)&cun, &socklen);printf("[%s]:%s\n",cun.sun_path, rbuf);//加个笑脸将消息回回去strcat(rbuf, "*_*");if(sendto(sfd, rbuf, strlen(rbuf), 0, (struct sockaddr*)&cun, sizeof(cun)) ==-1){perror("write error");return -1;}printf("发送成功\n");}//4、关闭套接字close(sfd);return 0;
}
通过TFTP用UDP实现上传和下载文件
#include <myhead.h>
#define SER_IP "192.168.125.99"
#define SER_PORT 69
#define IP "192.168.125.173"
#define PORT 8888
void download(char data[],short* p1,char* p2){char filename[128]="";printf("请输入要下载的文件名:");fgets(filename,sizeof(filename),stdin);filename[strlen(filename)-1]=0;int fp=open(filename,O_WRONLY | O_CREAT|O_TRUNC, 0664);//创建文件if(fp==-1){perror("open error");return ;}*p1=htons(1);//下载strcpy(p2,filename);char* p4=p2+strlen(filename)+1;strcpy(p4,"octet");int len=4+strlen(filename)+strlen("octet");printf("%s\n",p2);int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket error");return ;}struct sockaddr_in rin;rin.sin_family=AF_INET;rin.sin_port=htons(PORT);rin.sin_addr.s_addr=inet_addr(IP);if(bind(sfd,(struct sockaddr*)&rin,sizeof(rin))==-1){perror("bind error");return ;}printf("bind success\n");struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP); socklen_t sin_size = sizeof(sin); //发送下载请求sendto(sfd,data,len,0,(struct sockaddr*)&sin,sizeof(sin));char buf[516];short ack[2];ack[0]=htons(4);int res;while(1){bzero(buf,sizeof(buf));//接收数据到bufres=recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &sin_size);//返回接收数据字节数//从返回数据包中取出块编号,放到ack中去ack[1]=*(short*)(buf+2);//返回ACK确认sendto(sfd, ack, sizeof(ack), 0, (struct sockaddr*)&sin, sin_size);//将buf中的数据写到文件write(fp,buf+4,res-4);//写res-4个数据从buf+4位置到文件if(res!=516){break;}}close(fp);
}
void transmit(char data[],short* p1,char* p2){char filename[128]="";printf("请输入要上传的文件名:");fgets(filename,sizeof(filename),stdin);filename[strlen(filename)-1]=0;*p1=htons(2);//写,上传请求int fp=open(filename,O_RDONLY, 0664);//打开文件strcpy(p2,filename);char* p4=p2+strlen(filename)+1;strcpy(p4,"octet");int len=4+strlen(filename)+strlen("octet");int sfd=socket(AF_INET,SOCK_DGRAM,0);if(sfd==-1){perror("socket error");return ;}struct sockaddr_in rin;rin.sin_family=AF_INET;rin.sin_port=htons(PORT);rin.sin_addr.s_addr=inet_addr(IP);if(bind(sfd,(struct sockaddr*)&rin,sizeof(rin))==-1){perror("bind error");return ;}printf("bind success\n");struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP); socklen_t sin_size = sizeof(sin); //发送下载请求sendto(sfd,data,len,0,(struct sockaddr*)&sin,sizeof(sin));int count=1;*p1=htons(3);short* p10=data+2;while(1){*p10=htons(count);int ress=read(fp,data+4,512);if(ress==0){break;}sendto(sfd, data, sizeof(data), 0, (struct sockaddr*)&sin, sin_size);count++;}close(fp);
}
int main(int argc, const char *argv[])
{printf("1.下载2.上传");printf("请输入>>>");int flag=0;scanf("%d",&flag);while(getchar()!=10);char data[516]="";short* p1=data;char* p2=data+2;if(flag==1){download(data,p1,p2);}else if(flag==2){transmit(data,p1,p2);}return 0;
}