服务器
头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
//用户信息结构体
typedef struct node{
struct sockaddr_in cin;
int newfd;
int size;
struct node *next;
}USER;
#define PORT 8888 //1024~49151
#define IP "192.168.31.72" //本机IP ifconfig查看
#define PATH "./"
//创建链表
USER* create_list(int sfd);
//服务器发送线程
void* wri_send(void*arg);
//发送信息
int send_msg(int newfd,char *buf,int size);
//删除指定节点
int delet_point(USER *H,int sfd);
//处理客户端信息线程
void *deal_climsg(void *arg);
#endif
功能文件
#include "head.h"
//创建链表
USER * create_list(int sfd)
{
//创建链表
USER *H=(USER*)malloc(sizeof(USER));
if(NULL==H)
{
puts("链表创建失败");
return NULL;
}
//初始化链表
H->next=NULL;
H->size=0;
H->newfd=sfd;
return H;
}
//发送信息
int send_msg(int newfd,char *buf,int size)
{
ssize_t res;
if((res=send(newfd,buf,size,0))<0)
{
ERR_MSG("send");
return -1;
}
return 0;
}
//服务器发送系统信息线程
void* wri_send(void*arg)
{
pthread_detach(pthread_self());
char buf[128]="";
ssize_t res;
USER *H=(USER*)arg;
while(1)
{
bzero(buf,sizeof(buf));
//printf("请输入要传输的:\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
USER *p=H->next;
while(p!=NULL)
{
int newfd=p->newfd;
if(send_msg(newfd,buf,sizeof(buf))<0)
{
return NULL;
}
p=p->next;
}
}
}
//删除指定节点
int delet_point(USER *H,int sfd)
{
USER *p=H;
while(p->next!=NULL)
{
if(p->next->newfd == sfd)
{
USER *q=p->next;
p->next=q->next;
free(q);
q=NULL;
break;
}
p=p->next;
}
return 0;
}
//处理客户端信息线程
void *deal_climsg(void *arg)
{
pthread_detach(pthread_self());
USER *H=(USER*)arg;
USER *p=H;
while(p->next!=NULL)
{
p=p->next;
}
int newfd =p->newfd;
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 NULL;
}
else if(0==res)
{
printf("[%s : %d] newfd =%d客户端退出\n",inet_ntoa((p->cin).sin_addr),ntohs((p->cin).sin_port),newfd);
delet_point(H,newfd);
break;
}
if(strcmp(buf,"readdir")==0)
{
//打开指定目录
DIR* dp=opendir(PATH);
if(NULL== dp)
{
ERR_MSG("opendir");
return NULL;
}
struct dirent* rp=NULL;
//发送目录信息
char arr[128]="目录:";
send_msg(newfd,arr,sizeof(arr));
while(1)
{
bzero(arr,sizeof(arr));
rp=readdir(dp);
if(NULL == rp)
{
if(0==errno)
{
break;
}else
{
ERR_MSG("readdir");
return NULL;
}
}
if(rp->d_name[0]=='.')
continue;
strcpy(arr,rp->d_name);
send_msg(newfd,arr,sizeof(arr));
}
//关闭目录
closedir(dp);
}else if(strcmp(buf,"download")==0)
{
//判断并发送提示下载信息
char brr[128]="请选择要下载的文件:";
send_msg(newfd,brr,sizeof(brr));
bzero(brr,sizeof(brr));
ssize_t res1;
res1=recv(newfd,brr,sizeof(brr),0);
if(res1<0)
{
ERR_MSG("recv");
return NULL;
}
else if(0==res1)
{
printf("[%s : %d] newfd =%d客户端退出\n",inet_ntoa((p->cin).sin_addr),ntohs((p->cin).sin_port),newfd);
delet_point(H,newfd);
break;
}
//发送开始下载标示
char stat[128]="";
strcpy(stat,"开始发送");
send_msg(newfd,stat,sizeof(stat));
//打开要发送的文件
char crr[128]="";
strcpy(crr,PATH);
strcat(crr,brr);
printf("%s\n",crr);
int fd_r=open(crr,O_RDONLY);
if(fd_r<0)
{
ERR_MSG("open");
return NULL;
}
//循环读取发送信息
ssize_t res_rd;
int i=1;
while(1)
{
bzero(brr,sizeof(brr));
res_rd=read(fd_r,brr,sizeof(brr));
if(res_rd<0)
{
ERR_MSG("read");
return NULL;
}else if(0==res_rd)
{
printf("文件传输完成\n");
break;
}
send_msg(newfd,brr,res_rd);
}
}
printf("[%s : %d] newfd =%d:%s\n",inet_ntoa((p->cin).sin_addr),ntohs((p->cin).sin_port),newfd,buf);
}
}
主函数
#include "head.h"
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
//允许端口快速复用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
//填充地址信息结构体,真是的地址信息结构体与协议族相关
//AF_INET,所以详情请看man 7ip
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("bing success\n");
//将套接字设置为被动监听状态
if(listen(sfd,128)<0)
{
ERR_MSG("listen");
return -1;
}
printf("listen success\n");
//创建链表
USER *H=create_list(sfd);
if(NULL==H) return -1;
//网络字节序的IP-->点分十进制,网络字节序的port-->本机字节序
//printf("[%s : %d] newfd =%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
pthread_t tid1;
if(pthread_create(&tid1,NULL,wri_send,(void*)H)<0)
{
ERR_MSG("pthread_create");
return -1;
}
while(1)
{
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
//从已完成连接的队列头中,取出一个客户端的信息,创建生成一个新的套接字文件描述符
//该文件描述符才是与客户端通信的文件描述符
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
//判断是不是新的客户
USER *p=H;
while(p->next!=NULL)
{
if(newfd==p->newfd)
{
break;
}
p=p->next;
}
if(NULL==p->next)
{
//初始化新增节点
USER *new=(USER*)malloc(sizeof(USER));
new->newfd=newfd;
new->cin=cin;
new->next=NULL;
//尾插连入链表
p->next=new;
//表的变化
H->size++;
//创建新的客户线程
pthread_t tid2;
if(pthread_create(&tid2,NULL,deal_climsg,(void*)H)<0)
{
ERR_MSG("pthread_create");
return -1;
}
}
}
close(sfd);
return 0;
}
客户端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
//服务器IP和端口号
#define PORT 8888 //1024~49151
#define IP "192.168.31.72" //本机IP ifconfig查看
void* wri_send(void*arg)
{
pthread_detach(pthread_self());
char buf[128]="";
ssize_t res;
int sfd=*((int*)arg);
while(1)
{
printf("请输入要传输的:\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
res=send(sfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("send");
return NULL;
}
}
}
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success\n");
//允许端口快速复用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("setsockopt success\n");
//绑定客户端信息结构体
//填充要连接的服务器的地址信息结构体‘
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//连接服务器
if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("connect");
return -1;
}
//创建发送线程
pthread_t tid;
if(pthread_create(&tid,NULL,wri_send,(void*)&sfd)<0)
{
ERR_MSG("pthread_create");
return -1;
}
ssize_t res=0;
char arr[5]="";
char buf[128]="";
//发送
while(1)
{
//接收
bzero(buf,sizeof(buf));
res=recv(sfd,buf,sizeof(buf),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}else if(res==0)
{
printf("服务器关闭\n");
break;
}
printf("%s\n",buf);
if(strcmp(buf,"开始发送")==0)
{
int fd_w=open("copy.c",O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd_w<0)
{
ERR_MSG("open");
return -1;
}
//循环接收信息并写进文件
char brr[128]="";
ssize_t res_w;
while(1)
{
bzero(brr,sizeof(brr));
res_w=recv(sfd,brr,sizeof(brr),0);
if(res_w<0)
{
ERR_MSG("recv");
return -1;
}else if(res_w==0)
{
printf("服务器关闭\n");
return -1;
}
if(res_w
功能实现示例: