tcp 文件传输,tcp上传文件
这里写目录标题代码tcp_server.c代码说明:来源:微信公众号:图控大叔
tcp _ server.c #包含标准视频
#include sys/types.h /*参见注释*/
#包含sys/socket.h
#包含netinet/in.h
#包含netinet/ip.h
#包括arpa/inet.h
#包含字符串。h
#包括unistd.h
#包含标准库
#include pthread.h
#包含字符串。h
结构fifo_data
{
char FIFO _ name[32];
char FIFO _ type[32];
char FIFO _ buff[1024];
无符号long long数据长度
内部ret
};
结构消息_数据
{
int data _ size
char name[16];
结构fifo _数据myfifo
茶缓冲区[1024];
};
struct client_fd_sql{
int client _ FD[50];//文件描述符数组
int last//记录数组引用到哪一个元素
};
数据类型说明结构客户端信息{
int client _ fd
char name[256];
char IP[16];
短端口;
pthread _ t tid
struct client _ info * next
}客户端信息节点;
#define list_for_each(head,pos)\
for(pos=head-next;pos!=NULLpos=pos- next)
//申请客户端信息链表的头节点
静态客户端信息节点*请求客户端信息节点(常量客户端信息节点*信息)
{
客户端信息节点*新节点;
new _ node=malloc(sizeof(client _ info _ node)).
如果(新节点==空)
{
perror(’申请客户端节点异常);
返回空
}
如果(信息!=空)
*新节点=*信息
new _ node-next=NULL;
返回新节点;
}
静态内联void插入客户端信息节点链接列表(客户端信息节点*头,客户端信息节点*插入_节点)
{
客户端信息节点*位置;
for(pos=head;力量下一个!=null pos=pos-next);
pos-next=insert _ node;
}
无效*客户端线程(void *arg)
{
int client _ fd
结构消息_数据接收消息;
接收大小,发送大小
client_info_node *pos,* list _ head=arg
每个的列表(列表头,位置)
{
if(pthread_self()==pos- tid)
{
client _ FD=pos-client _ FD;
打破;
}
}
while(1)
{
bzero( recv_msg,sizeof(recv _ msg));
/*
接受来自与客户端的数据,这个接受具备阻塞特性
跟阅读函数差不多,都是指定从client_fd里面读取sizeof(缓冲)长的数据放到缓冲器当中,0则代表按照默认操作读取数据
*/
recv_size=recv(client_fd,recv_msg,sizeof(recv_msg),0);
if(recv_size==-1)
{
perror(’接受数据异常);
打破;
}
else if(recv_size==0)//代表客户端断开连接
{
//删除链表节点
打破;
}
每个的列表(列表头,位置)
{
if(pos- client_fd==client_fd)
继续;
printf(转发数据给端口号为%hu\n ,位置-端口);
send_size=send( pos- client_fd,recv_msg,sizeof(recv_msg),0);
if(send_size==-1)
打破;
}
printf(接收到来自与客户端%ld个字节的数据:%s\n ,recv_size,recv _ msg。缓冲);
}
返回空
}
int main(void)
{
int skt _ fd
返回值
客户端信息节点*列表头*新节点;
客户端信息节点缓存客户端信息;
接收大小,发送大小
list_head=请求_客户端_信息_节点(空);
/*
获取程序通信的套接字(接口)
网络:IPV4的协议
袜子_流:指定三氯苯酚协议
0:代表不变化协议内部(ip手册中指定的参数)
*/
skt_fd=socket( AF_INET,SOCK_STREAM,0);
if(skt_fd==-1)
{
perror(’申请套接字失败);
return-1;
}
int SW=1;
//端口绑定复用
retval=setsockopt(skt_fd,SOL_SOCKET,SO_REUSEADDR,sw,sizeof(SW));
结构sockaddr _ in本机地址
native _ addr。sin _家庭=AF _ INET//指定引用IPV4的协议
native _ addr。sin _ port=htons(6666);//指定端口号,转化为网络字节序(大端序)
//inet_aton(INADDR_ANY,(native _ addr。sin _ addr));
native _ addr。sin _ addr。s _ addr=htonl(在addr _ ANY中);//将所有的互联网协议(互联网协议)地址转化为二进制的网络字节序的数据进行绑定
retval=bind( skt_fd,(struct sockaddr *) native_addr,sizeof(native _ addr));
if(retval==-1)
{
perror(’绑定套接字地址失败);
转到bind _ socket _ err
}
retval=listen(skt_fd,50);
if(retval==-1)
{
perror(’设置最大连接数失败);
转到set _ listen _ err
}
int client _ fd
客户端地址中的结构sockaddr _ in
socklen _ t sklen=sizeof(client _ addr);
//int client _ FD;
结构客户端_ FD _ SQL客户端_ FDS={ .last=-1 };
int I;
int max _ fd=skt _ fd
fd _ set readfds
FD _ ZERO(读FDS);
结构消息_数据接收消息;
while(1)
{
FD_SET(0,读FDS);//将标准输入的文件描述符放到集合里面
FD_SET(skt_fd,读FDS);//网络链接的文件描述符放到集合里面
for(I=0;i=client _ fds.last我)
{
FD_SET(client_fds.client_fd[i],读FDS);
}
retval=select(max_fd 1,readfds,NULL,NULL,NULL);
if(retval==-1)
{
perror(’复用等待异常);
转到select _ err
}
else if(retval==0)
{
printf(服用等待超时\ n’);
}
else if(retval)//如果真的有文件描述符相应,则进入这个判断
{
for(I=0;i=client _ fds.last我)
{
if(FD _ ISSET(client _ FDS。client _ FD[I],readfds))
{
bzero( recv_msg,sizeof(recv _ msg));
recv _ size=recv(客户端_ FDS。client _ FD[I],recv_msg,sizeof(recv_msg),0);
if(recv_size==-1)
{
perror(’读取数据异常);
继续;
}else if(recv_size==0)
{
printf(客户端断开链接\ n’);
memcpy(client_fds.client_fd i,client_fds.client_fd i 1,client_fds。last-I);
客户_ FDS。最后-;
打破;
}
客户端信息节点*位置;
每个的列表(列表头,位置)
{
if(pos-client _ FD==client _ FDS。client _ FD[I])
继续;
printf(转发数据给端口号为%hu\n ,位置-端口);
send_size=send( pos- client_fd,recv_msg,sizeof(recv_msg),0);
if(send_size==-1)
打破;
}
printf(接收到来自与客户端%ld个字节的数据:%s\n ,recv_size,recv _ msg。缓冲);
//printf(recv data=%s\n ,buffer);
}
}
if(FD_ISSET(0,readfds))//如果0号文件描述符还在集合中,便证明我们当前的相应便是标准输入发起的
{
bzero( recv_msg,sizeof(recv _ msg));
扫描f(%s ,接收消息。缓冲);
printf(从键盘当中获取到:%s\n ,recv _ msg。缓冲);
}
if(FD_ISSET(skt_fd,readfds))//如果skt_fd在集合中,则证明是有客户端链接服务器,我们才相应了
{
缓存客户端信息。client _ FD=accept(SKT _ FD,(结构sockaddr *) client_addr,sk len);
if(缓存_客户端_信息。client _ FD==-1)
{
perror(’客户端链接失败);
转到客户端连接错误
}
strcpy(cache_client_info.ip,inet _ ntoa(client _ addr。sin _ addr));//存放互联网协议(互联网协议)地址
缓存客户端信息。port=ntohs(client _ addr。sin _ port);
//新建节点
新节点=请求_客户端_信息_节点(缓存_客户端_信息);
//将节点插入链表
插入客户端信息节点链接列表(列表头,新节点);
printf(服务器:客户端连接成功\ n’);
printf(客户端信息:\n客户端互联网协议(互联网协议)为%s,端口号为%hu\n ,cache_client_info.ip,cache_client_info。港口);
client _ fds.last
客户_ FDS。FDS客户端。last]=client _ FD;
max_fd=max_fd client_fd?max _ FD:client _ FD;
pthread_create( (new_node- tid),NULL,client_thread,list _ head);
}
}
}
close(client _ FD);//关闭客户端通信
关闭(SKT _ FD);//关闭服务器的窝资源
返回0;
套接字_接收_错误:
选择错误:
close(client _ FD);
客户端连接错误:
设置监听错误:
绑定套接字错误:
关闭(SKT _ FD);
return-1;
}
tcp _ client.c #包含标准视频
#include sys/types.h /*参见注释*/
#包含sys/socket.h
#包含netinet/in.h
#包含netinet/ip.h
#包括arpa/inet.h
#包含字符串。h
#包括unistd.h
#包含字符串。h
#include pthread.h
#包含系统/统计信息
#包含fcntl.h
#include sys/mman.h
#定义建筑环境及HVAC系统模拟的软件平台文件。/06.rar //对路径进行宏定义
int fd1
int fd2
结构fifo_data
{
char FIFO _ name[32];
char FIFO _ type[32];
char FIFO _ buff[1024];
无符号long long数据长度
内部ret
};
结构消息_数据
{
int data _ size
char name[16];
结构fifo _数据myfifo
茶缓冲区[1024];
};
void *recv_data(void *arg)
{
int SKT _ FD=*(int *)arg;
结构消息_数据发送消息,接收消息;
ssize _ t接收大小
发送大小
printf( recv _ data \ n );
while(1)
{
bzero((send _ msg。我的先进先出。FIFO _ buff)、sizeof(send _ msg。我的先进先出。FIFO _ buff));
bzero( recv_msg,sizeof(recv _ msg));
/*
接受来自与客户端的数据,这个接受具备阻塞特性
跟阅读函数差不多,都是指定从client_fd里面读取sizeof(缓冲)长的数据放到缓冲器当中,0则代表按照默认操作读取数据
*/
recv_size=recv(skt_fd,recv_msg,sizeof(recv_msg),0);
if(recv_size==-1)
{
perror(’接受数据异常);
打破;
}
printf(数据为%llu字节\n ,接收消息。我的先进先出。data _ len);
send_msg.myfifo.ret=read(fd1,send_msg.myfifo.fifo_buff,1024);
if(send_msg.myfifo.ret==0)
{
printf(复制%llu字节,读取已完成!\n ,发送消息。我的先进先出。data _ len);
发送_消息。data _ size=sizeof(send _ msg);
send_size=send( skt_fd,send_msg,send_msg.data_size,0);
if(send_size==-1)
printf(发送出错\ n’);
打破;
}
发送_消息。我的先进先出。数据长度=发送信息。我的先进先出。ret send _ msg我的先进先出。data _ len
发送_消息。data _ size=sizeof(send _ msg);
send_size=send( skt_fd,send_msg,send_msg.data_size,0);
//printf(" ");
if(send_size==-1)
printf(发送出错\ n’);
}
返回空
}
void *recv_data22(void *arg)
{
int SKT _ FD=*(int *)arg;
结构消息_数据发送消息,接收消息;
ssize _ t接收大小
发送大小
printf( recv _ data 22 \ n );
while(1)
{
bzero( recv_msg,sizeof(recv _ msg));
/*
接受来自与客户端的数据,这个接受具备阻塞特性
跟阅读函数差不多,都是指定从client_fd里面读取sizeof(缓冲)长的数据放到缓冲器当中,0则代表按照默认操作读取数据
*/
recv_size=recv(skt_fd,recv_msg,sizeof(recv_msg),0);
if(recv_size==-1)
{
perror(’接受数据异常);
打破;
}
if(recv_msg.myfifo.ret==0)
{
printf(文件传输完毕,长度为%llu\n ,recv _ msg。我的先进先出。data _ len);
关闭(fd2);
打破;
}
写(fd2,recv_msg.myfifo.fifo_buff,recv_msg。我的先进先出。ret);
printf(数据为%llu字节\n ,接收消息。我的先进先出。data _ len);
发送_消息。我的先进先出。数据长度=发送信息。我的先进先出。ret send _ msg我的先进先出。data _ len
发送_消息。data _ size=sizeof(send _ msg);
send_size=send( skt_fd,send_msg,send_msg.data_size,0);
if(send_size==-1)
printf(发送出错\ n’);
}
返回空
}
//./客户端服务器互联网协议(互联网协议)名字
int main(int argc,const char *argv[])
{
int skt _ fd
返回值
skt_fd=socket( AF_INET,SOCK_STREAM,0);
if(skt_fd==-1)
{
perror(’申请套接字失败);
return-1;
}
结构sockaddr _ in srv _ addr
srv _ addr.sin _ family=AF _ INET//指定引用IPV4的协议
SRV _ addrsin _ port=htons(6666);//指定端口号,转化为网络字节序(大端序)
SRV _ addrsin _ addr。s _ addr=inet _ addr(argv[1]);//将所有的互联网协议(互联网协议)地址转化为二进制的网络字节序的数据进行绑定
retval=connect(skt_fd,(struct sockaddr *) srv_addr,sizeof(SRV _ addr));
if(retval==-1)
{
perror(’客户端连接到服务器失败\ n’);
转至connect _ server _ err
}
printf(客户端:连接服务器成功\ n’);
结构消息_数据发送消息;
stpcpy(send_msg.name,argv[2]);
发送大小
printf(接收:1\n还是发送:2 \ n’);
scanf(%d ,retval);
if(retval==1)
{
fd2=打开(。/07.rar ,O_WRONLY O_CREAT O_TRUNC,0777);
pthread _ t tid
pthread_create( tid,NULL,recv_data22,SKT _ FD);
}
其他
{
fd1=开放(DEST文件,O _ RDONLY);
如果(fd1==-1)
{
printf(打开%s失败!\n ,DEST _文件);//s错误把错误码转化成错误提示
return-1;
}
发送_消息。我的先进先出。数据长度=0;
send_msg.myfifo.ret=read(fd1,send_msg.myfifo.fifo_buff,1024);
printf(%d \n ,send _ msg。我的先进先出。ret);
发送_消息。我的先进先出。数据长度=发送信息。我的先进先出。ret send _ msg我的先进先出。data _ len
发送_消息。data _ size=sizeof(send _ msg);
send_size=send( skt_fd,send_msg,send_msg.data_size,0);
if(send_size==-1)
printf(发送出错\ n’);
pthread _ t tid
pthread_create( tid,NULL,recv_data,SKT _ FD);
}
while(1)
{
bzero( (send_msg.buffer),sizeof(send _ msg。缓冲));
scanf(%s ,send _ msg。缓冲);
发送_消息。data _ size=sizeof(send _ msg);
send_size=send( skt_fd,send_msg,send_msg.data_size,0);
if(send_size==-1)
打破;
}
关闭(SKT _ FD);
返回0;
连接服务器错误:
关闭(SKT _ FD);
return-1;
}
代码说明:1、服务器只是负责转发消息
2.客户端已经设置了端口重用。
3.要发送的文件名路径已经设置好了,要测试的需要自己改。
4.客户端代码匆忙上线,只有基本的文件发送功能。
微信官方账号:图控大叔
,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。