TCP多并发服务器
多线程
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void* test_send(void* arg){
char buf[20]="";
int accfd=*(int *)arg;
while(1){
bzero(buf,sizeof(buf));
//sleep(1);
printf("请输入:\n");
scanf("%s",buf);
int sndres=send(accfd,(void*)buf,sizeof(buf),0); //发送信息给客户端
if(sndres>0){
printf("已发送%d个字节\n",sndres);
}else if(sndres<0){
perror("send");
}
}
close(accfd);
pthread_exit(NULL);
}
void* test_recv(void* arg){
char buf[20];
int accfd=*(int *)arg;
while(1){
bzero(buf,sizeof(buf));
int recres=recv(accfd,(void*)buf,sizeof(buf),0); //接收客户端信息
if(recres>0){
printf("已接受%d个字节\n",recres);
printf("res=%s\n",buf);
}else if(recres==0){
printf("客户端已关闭\n");
break;
}else{
perror("recv");
return NULL;
}
}
close(accfd);
pthread_exit(NULL);
}
void main_serv(){
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(8888); //端口号 本机字节序--->网络字节序
addr.sin_addr.s_addr=inet_addr("192.168.8.207"); //ip 本机字节序--->网络字节序
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
perror("socket");
return;
}
//端口号快速重用
int reuse=1;
if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &reuse ,sizeof(reuse))<0){
perror("setsockopt");
return;
}
if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0){
perror("bind");
return;
}
if(listen(sockfd,32)!=0){
perror("listen");
return;
}
struct sockaddr_in raddr;
int len=sizeof(raddr);
pthread_t tid_s;
pthread_t tid_r;
int accfd;
while(1){
accfd=accept(sockfd,(struct sockaddr*)&raddr,&len);
if(accfd<0){
perror("accept");
return;
}
// char* ip=inet_ntoa(raddr.sin_addr);
// printf("ip:%s\n",ip);
/*
char w_buf[20]="rogar";
char r_buf[20]="";
while(1){
int recres=recv(accfd,r_buf,sizeof(r_buf),0); //接收客户端信息
if(recres>0){
printf("已接受%d个字节\n",recres);
printf("%s\n",r_buf);
}else if(recres==0){
printf("客户端已关闭\n");
break;
}else{
perror("recv");
return ;
}
int sndres=send(accfd,w_buf,sizeof(w_buf),0); //发送信息给客户端
if(sndres>0){
printf("已发送%d个字节\n",sndres);
}else if(sndres<0){
perror("send");
}
}
*/
// pthread_t tid_s;
// pthread_t tid_r;
pthread_create(&tid_s,NULL,test_send,(void*)&accfd);
pthread_create(&tid_r,NULL,test_recv,(void*)&accfd);
pthread_detach(tid_s);
pthread_detach(tid_r);
}
//close(accfd);
close(sockfd);
}
int main(){
main_serv();
}
多进程
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
/*
void* test_send(void* arg){
char buf[20]="";
int accfd=*(int *)arg;
while(1){
bzero(buf,sizeof(buf));
//sleep(1);
printf("请输入:\n");
scanf("%s",buf);
int sndres=send(accfd,(void*)buf,sizeof(buf),0); //发送信息给客户端
if(sndres>0){
printf("已发送%d个字节\n",sndres);
}else if(sndres<0){
perror("send");
}
}
}
void* test_recv(void* arg){
char buf[20];
int accfd=*(int *)arg;
while(1){
bzero(buf,sizeof(buf));
int recres=recv(accfd,(void*)buf,sizeof(buf),0); //接收客户端信息
if(recres>0){
printf("已接受%d个字节\n",recres);
printf("res=%s\n",buf);
}else if(recres==0){
printf("客户端已关闭\n");
break;
}else{
perror("recv");
return NULL;
}
}
}
*/
void handler(int sig){
while(waitpid(-1,NULL,WNOHANG)>0);
}
void main_serv(){
signal(SIGCHLD,handler);
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(8888); //端口号 本机字节序--->网络字节序
addr.sin_addr.s_addr=inet_addr("192.168.8.207"); //ip 本机字节序--->网络字节序
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
perror("socket");
return;
}
//端口号快速重用
int reuse=1;
if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &reuse ,sizeof(reuse))<0){
perror("setsockopt");
return;
}
if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0){
perror("bind");
return;
}
if(listen(sockfd,32)!=0){
perror("listen");
return;
}
struct sockaddr_in raddr;
int len=sizeof(raddr);
while(1){
int accfd=accept(sockfd,(struct sockaddr*)&raddr,&len);
if(accfd<0){
perror("accept");
return;
}
pid_t pid=fork();
if(pid>0){
//父进程负责监听
close(accfd);
}else if(pid==0){
//子进程负责接收发送
close(sockfd);
char r_buf[20]="";
while(1){
int recres=recv(accfd,r_buf,sizeof(r_buf),0); //接收客户端信息
if(recres>0){
printf("已接受%d个字节\n",recres);
printf("%s\n",r_buf);
}else if(recres==0){
printf("客户端已关闭\n");
break;
}else{
perror("recv");
return ;
}
char w_buf[10]="okok";
int sndres=send(accfd,w_buf,sizeof(w_buf),0); //发送信息给客户端
if(sndres>0){
printf("已发送%d个字节\n",sndres);
}else if(sndres<0){
perror("send");
}
}
exit(0);
}else{
perror("fork");
return;
}
}
/*
char w_buf[20]="rogar";
char r_buf[20]="";
while(1){
int recres=recv(accfd,r_buf,sizeof(r_buf),0); //接收客户端信息
if(recres>0){
printf("已接受%d个字节\n",recres);
printf("%s\n",r_buf);
}else if(recres==0){
printf("客户端已关闭\n");
break;
}else{
perror("recv");
return ;
}
int sndres=send(accfd,w_buf,sizeof(w_buf),0); //发送信息给客户端
if(sndres>0){
printf("已发送%d个字节\n",sndres);
}else if(sndres<0){
perror("send");
}
}
*/
/*
pthread_t tid_s;
pthread_t tid_r;
pthread_create(&tid_s,NULL,test_send,(void*)&accfd);
pthread_create(&tid_r,NULL,test_recv,(void*)&accfd);
pthread_join(tid_r,NULL);
pthread_join(tid_s,NULL);
*/
//close(accfd);
close(sockfd);
}
int main(){
main_serv();
}
tftp 下载上传
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
/*
typedef struct {
int sockfd;
struct sockaddr_in dest;
}node;
*/
void download(int sockfd,struct sockaddr_in addr){
char filename[20]="";
char buf[516];
bzero(filename,sizeof(filename));
printf("输入文件名:\n");
//scanf("%s",filename);
//while(getchar()!='\n'){}
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]=0;
//读写请求拼接
// struct sockaddr_in dest_server=n->dest;
//操作码 1--下载 2--上传
short* p_code=(short*)buf;
*p_code=htons(1);
//文件名
char* p_filename=(char *)buf+2;
strcpy(p_filename,filename);
//标识1
char *p_flag1=(char *)buf+2+strlen(filename);
*p_flag1=0;
//模式
char *p_mode=(char *)buf+2+strlen(filename)+1;
strcpy(p_mode,"octet");
// 标识2
char *p_flag2=(char *)buf+2+strlen(filename)+1+5;
*p_flag2=0;
int size=1+2+1+5+strlen(filename);
//发送读写请求
if(sendto(sockfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
perror("48---sendto");
return ;
}
//接收数据
char buf_recv[600]; //接收数据的数组
char* get_bid=buf_recv+2; //数据包块编号
char* get_data=buf_recv+4; //数据包数据
char ack[4]; //ACK包
short* ack_code=(short*)ack; //ACK操作码
short* ack_bid=(short*)ack+1; //ACK编号
int res;
int fd=-1;
int flag=0;
struct sockaddr_in rec;
int len=sizeof(rec);
while(1){
if((res=recvfrom(sockfd,buf_recv,sizeof(buf_recv),0,(struct sockaddr*)&rec,&len))<516){
if(buf_recv[1]==5){
fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf_recv+2)), buf_recv+4);
break;
}
printf("接收完毕\n");
break;
}
if(res<0){
return;
}
if(buf_recv[1]==3){
if(flag==0){
int fd=open(filename,O_RDWR|O_CREAT,0777);
if(fd<0){
perror("open");
return ;
}
flag=1;
}
write(fd,get_data,res-4);
//组ACK
*ack_code=htons(4);
*ack_bid=*(short*)get_bid;
//发送ACK
sendto(sockfd,ack,4,0,(struct sockaddr*)&rec,sizeof(rec));
}else if(buf_recv[1]==5){
fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf_recv+2)), buf_recv+4);
break;
}
}
//组ACK
*ack_code=htons(4);
*ack_bid=*(short*)get_bid;
//发送ACK
sendto(sockfd,ack,4,0,(struct sockaddr*)&rec,sizeof(rec));
write(fd,get_data,res-4);
close(fd);
}
void upload(int sockfd,struct sockaddr_in addr){
char filename[20]="";
bzero(filename,sizeof(filename));
printf("输入文件名:\n");
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]=0;
//读写请求拼接
char buf[128];
// struct sockaddr_in dest_server=np->dest;
//操作码 1--下载 2--上传
short* p_code=(short*)buf;
*p_code=htons(2);
//文件名
char* p_filename=(char *)buf+2;
strcpy(p_filename,filename);
//标识1
char *p_flag1=(char *)buf+2+strlen(filename);
*p_flag1=0;
//模式
char *p_mode=(char *)buf+2+strlen(filename)+1;
strcpy(p_mode,"octet");
// 标识2
char *p_flag2=(char *)buf+2+strlen(filename)+1+5;
*p_flag2=0;
int size=1+2+1+5+strlen(filename);
//发送读写请求
if(sendto(sockfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
perror("sendto");
return ;
}
//打开文件
int fd=open(filename,O_RDWR);
if(fd<0){
perror("open");
return;
}
char str[600]; //数据包
char buf_r[512]; //文件读取存储数组
char temp[4]; //ACK存储数组
short* data_code=(short*)str;
short* data_id=(short*)str+1;
char* data=str+4;
short* ack_code=(short*)temp;
short* ack_bid=(short*)temp+1;
int res;
short num=1; //块编号
struct sockaddr_in ack;
int len=sizeof(ack);
recvfrom(sockfd,temp,4,0,(struct sockaddr*)&ack,&len);//接收服务器ack
while(1){
//组数据包
*data_code=htons(3); //数据包操作码
*data_id=htons(num); //数据包编号
num++;
if((res=read(fd,buf_r,sizeof(buf_r)))<512){
break;
}
strcpy(data,buf_r);
sendto(sockfd,str,res+4,0,(struct sockaddr*)&ack,sizeof(ack));
recvfrom(sockfd,temp,4,0,(struct sockaddr*)&ack,&len);//接收服务器ack
}
strcpy(data,buf_r);
sendto(sockfd,str,res+4,0,(struct sockaddr*)&ack,sizeof(ack));
printf("上传完成\n");
close(fd);
}
/*
node* client_tftp(){
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
perror("sockfd");
return NULL;
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(69);
addr.sin_addr.s_addr=inet_addr("192.168.8.226");
bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
node n;
node *p=&n;
p->sockfd=sockfd;
p->dest=addr;
return p;
}
*/
int main(int argc ,char *argv[]){
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
perror("sockfd");
return 0;
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(69);
addr.sin_addr.s_addr=inet_addr("192.168.8.226");
bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
char c;
while(1){
system("clear");
printf("=======================\n");
printf("=======1.下载==========\n");
printf("=======2.上传==========\n");
printf("=======3.退出==========\n");
printf("=======================\n");
printf("请输入选项:");
c=getchar();
while(getchar()!=10);
switch(c){
case '1':
download(sockfd,addr);
break;
case '2':
upload(sockfd,addr);
break;
case '3':
printf("已退出");
exit(0);
break;
default:
printf("输入不正确\n");
}
printf("输入回车继续");
while(getchar()!=10){}
}
close(sockfd);
return 0;
}