参考书本做了一个简易的文件传输系统,对网络编程,文件操作进行复习。

系统调用socket

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

int socket(int domain,int type,int protocol)

参数

domain:网络程序所在的主机采用的通用协议簇(AF_UNIX、AF_INET等)AF_UNIX只能够用于单一的UNIX系统进程间通信,而AF_INET是针对internet的,允许在远程主机之间通信

type:网络程序所采用的通信协议,可以理解成套接字的类型。其中SOCK_STREAM代表流式套接字,即表明采用TCP的协议;SOCK_DGRAM为数据报套接字,即表明采用UDP的协议

SOCK_RAW代表原始套接字

protocol:如果type指定为SOCK_STREAM或SOCK_DGRAM,则已经确定协议,所以protocol置0;如果指定SOCK_RAW,还需要进一步指定协议,通过protocol指定,如IPPROTO_ICMP

返回值

成功:返回一个新的套接字描述符

失败:返回-1,并置错误码

系统调用bind

头文件

#include <sys/socket.h>
#include <sys/types.h>

#include <arpa/inet.h>

原型

int bind(int sockfd,struct sockaddr *my_addr,socklen_t addrlen)

功能

绑定本机地址到套接字上

参数

sockfd:由socket调用返回的套接字描述符

my_addr:一个指向sockaddr的指针,实际应用中,一般使用指向struct sockaddr_in的指针代替

addrlen:sockaddr结构的长度

返回值

成功:返回0

失败:返回-1,并置错误码

备注

1:设置端口号时,可以选择大于1024的端口号;如果端口号为0,则表明由系统自动分配的端口号

2:设置ip地址时,如果地址为INADDR_ANY,则表明自动加载本地ip

系统调用listen

头文件

#include <sys/socket.h>

原型

int listen(int sockfd,int backlog)

功能

在bind对应的地址和端口上监听

参数

sockfd: 由socket调用返回的套接字描述符

backlog:请求队列的大小,一般为20

返回值

成功:返回为0

失败:返回-1,并置错误码

备注

backlog并不代表服务器端可同时处理的客户端个数,而是向服务器端同时发起连接请求的客户端的个数

系统调用accept

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

int accept(int sockfd,struct sockaddr *addr socklen_t *addrlen)

功能

接收客户端的连接请求

参数

sockfd: 由socket调用返回的套接字描述符

addr与addrlen:用来给客户端的程序填写的,服务器端只用传递对应类型的指针

返回值

成功:返回为0

失败:返回-1,并置错误码

系统调用connect

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

int accept(int sockfd,struct sockaddr *addr, socklen_t *addrlen)

功能

接收客户端的连接请求

参数

sockfd: 由socket调用返回的套接字描述符

addr与addrlen:用来给客户端的程序填写的,服务器端只用传递对应类型的指针

返回值

成功:返回为0

失败:返回-1,并置错误码

系统调用send

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

ssize_t send(int s,const void* buf,size_t len,int flags)

功能

面向连接的套接字发送数据

参数

s:由socket调用返回的套接字描述符

buf:即将发送的数据区域的首地址

len:发送的数据区域字节个数

flags:标志位

0:表明此时send功能与write相同

MSG_DONTROUTE:目标为本地主机,告诉ip协议不查找路由表

返回值

成功:返回已经成功发送的字节个数

失败:返回-1,并置错误码

系统调用sendto

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

ssize_t sendto(int s,const void* buf,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);

功能

面向连接或面向无连接的套接字发送数据

参数

s:由socket调用返回的套接字描述符

buf:即将发送的数据区域的首地址

len:发送的数据区域字节个数

flags:标志位

0:表明此时send功能与write相同

MSG_DONTROUTE:目标为本地主机,告诉ip协议不查找路由表

to:对方地址信息

tolen:对方字节

返回值

成功:返回已经成功发送的字节个数

失败:返回-1,并置错误码

系统调用recv

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

ssize_t recv(int s, void* buf,size_t len,int flags);

功能

面向连接的套接字接收数据

参数

s:由socket调用返回的套接字描述符

buf:即接收的数据区域的首地址

len:接收的数据区域字节个数

flags:标志位

0:表明此时recv功能与read相同

MSG_PEEK:只查看数据,不读出数据,下一次还能读到刚才的数据

MSG_WAITALL:等希望接收的数据字节个数到达个数到达后返回,否则阻塞等待,接收等待的条件:读到指定的字节数据,读到文件结束符,被信号中断,发生错误

返回值

成功:返回已经成功发送的字节个数

失败:返回-1,并置错误码

系通调用recvfrom

头文件

#include <sys/socket.h>

#include <sys/types.h>

原型

ssize_t recvfrom(int s, void* buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen);

功能

面向连接或面向无连接的套接字接收数据

参数

s:由socket调用返回的套接字描述符

buf:即接收的数据区域的首地址

len:接收的数据区域字节个数

flags:标志位

0:表明此时recv功能与read相同

MSG_PEEK:只查看数据,不读出数据,下一次还能读到刚才的数据

MSG_WAITALL:等希望接收的数据字节个数到达个数到达后返回,否则阻塞等待,接收等待的条件:读到指定的字节数据,读到文件结束符,被信号中断,发生错误

from:对方地址信息

fromlen:保存对方地址长度

返回值

成功:返回已经成功发送的字节个数

失败:返回-1,并置错误码

服务器端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <error.h>
#include <fcntl.h>


#define MAXDATASIZE                 128
#define SERVPORT                    5623
#define BACKLOG                     5


void process_cli(int connfd,struct sockaddr_in client);
void proc_ls(int);
void proc_get(int,char*);
void proc_put(int,char*);

int main()
{
	int listenfd,connfd;
	struct sockaddr_in ser_addr,cli_addr;
    int len;
	pid_t pid;
	
	if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		printf("socket error!!!\n");
	}
	
	
	bzero(&ser_addr,sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(SERVPORT);
	ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	//bzero(&(ser_addr.sin_zero),8);
	
	if((bind(listenfd,(struct sockaddr *)&ser_addr,sizeof(struct sockaddr_in)))<0)
	{
		printf("bind");
		exit(1);
	}
	if(listen(listenfd,BACKLOG) < 0)
	{
		printf("listen");
		exit(1);
	}
	bzero(&cli_addr,sizeof(cli_addr));
	
	len = sizeof(struct sockaddr_in);
	while(1)
	{
		printf("-----------------------------\n");
		
		if((connfd = accept(listenfd,(struct sockaddr *)&cli_addr,&len)) < 0)
		{
			printf("accept");
			exit(1);
		}
		
		if((pid = fork()) > 0)
		{
			close(connfd);
			continue;
		}
		else if(pid == 0)
		{
			close(listenfd);
			process_cli(connfd,cli_addr);
			exit(0);
		}
		else
		{
			printf("fork");
			exit(0);
		}
		
		
	}
	
    close(listenfd);
	
    return 0;
}

int parse(char *buf,char **args)
{
	int num = 0;
	
	while(*buf != '\0')
	{
      while((*buf == ' ')||(*buf == '\t'||(*buf == '\n')))
		  *buf++ = '\0';
	    *args++=buf;
		++num;
	  while((*buf!='\0')&&(* buf!=' ')&&(*buf!='\t')&&(*buf!='\n'))
		  buf++;
	  
	}
	
	*args = '\0';
	return num;
		
		
}

void process_cli(int connfd,struct sockaddr_in client)
{
	char cmd[MAXDATASIZE];
	char *cmds[64];
	
	int cmdnum,num;
	
	bzero(cmd,MAXDATASIZE);
	
	num = recv(connfd,cmd,MAXDATASIZE,0);
	
	if(num == -1)
	{
		close(connfd);
		printf("recv");
		exit(1);
	}
	cmd[num - 1]= '\0';
	
	printf("%s command is %s.\n",inet_ntoa(client.sin_addr),cmd);
	
	cmdnum = parse(cmd,cmds);
	
	if(strcmp(cmds[0],"exit") == 0)
	{
		close(connfd);
		exit(0);
	}
	else if(strcmp(cmds[0],"ls") == 0)
	{
		proc_ls(connfd);
	}
	else if(strcmp(cmds[0],"get") == 0)
	{
		if(cmds[1] != 0)
		{
			proc_get(connfd,cmds[1]);
		}
		else
		{
			printf("error: get command missing filename\n");
			close(connfd);
		}
		
	}
	else if(strcmp(cmds[0],"put") == 0)
	{
		if(cmds[1] != 0)
		{
			proc_put(connfd,cmds[1]);
		}
		else
		{
			printf("error: put command missing filename\n");
			close(connfd);
		}
	}
	
}



void proc_ls(int sockfd)
{
	DIR *mydir = NULL;
	struct dirent* myitem = NULL;
	char cmd[MAXDATASIZE];
	bzero(cmd,MAXDATASIZE);
	
	if((mydir=opendir(".")) == NULL)
	{
		printf("opendir");
		exit(1);
	}
	
	while((myitem = readdir(mydir)) != NULL)
	{
		if(sprintf(cmd,myitem->d_name,MAXDATASIZE) < 0)
		{
			printf("sprintf error");
			exit(1);
		}
		
		if(write(sockfd,cmd,MAXDATASIZE) < 0)
		{
			printf("write");
			exit(1);
		}
		
	}
	
	closedir(mydir);
	close(sockfd);
	return;
}
	
void proc_get(int sockfd,char* filename)
{
	int fd,nbytes;
	char buffer[MAXDATASIZE];
	bzero(buffer,MAXDATASIZE);
	
	
	printf("get filename: [%s]\n",filename);
	
	if((fd = open(filename,O_RDONLY)) < 0)
	{
		printf("open");
		buffer[0] = 'N';
		if(write(sockfd,buffer,MAXDATASIZE)<0)
		{
			printf("prco_get write1");
			exit(1);
		}
		return;
	}
	
	
	buffer[0] = 'Y';
	if(write(sockfd,buffer,MAXDATASIZE)<0)
	{
		printf("proc_get write2");
        close(fd);
        exit(1);
	}
	
	while((nbytes = read(fd,buffer,MAXDATASIZE)) > 0)
	{
		if(write(sockfd,buffer,nbytes) < 0)
		{
			printf("proc_get write3");
			close(fd);
			exit(1);
		}
	}
	
	close(fd);
	close(sockfd);
	
    return ;
}
	
void proc_put(int sockfd,char *filename)
{
	int fd,nbytes;
	char buffer[MAXDATASIZE];
	bzero(buffer,MAXDATASIZE);
	
	printf("get filename:[%s]\n",filename);
	
	if((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
	{
		printf("open");
		return;
	}
	
	while((nbytes=read(sockfd,buffer,MAXDATASIZE)) > 0)
	{
		if(write(fd,buffer,nbytes) < 0)
		{
			printf("proc_put write");
			close(fd);
			exit(1);
		}
	}
	
	close(fd);
	close(sockfd);
}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <error.h>
#include <fcntl.h>


#define N                256
#define PORT             5623


typedef struct sockaddr SA;


void proc_menu();
void proc_exit();
void proc_ls(struct sockaddr_in,char *);
void proc_get(struct sockaddr_in,char *);
void proc_put(struct sockaddr_in,char *);


int main(int argc,char *argv[])
{
	char cmd[N];
	struct sockaddr_in addr;
	int len;
	proc_menu();
	bzero(&addr,sizeof(addr));
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	len = sizeof(addr);
	
	while(1)
	{
		printf(">");
		bzero(cmd,N);
		if(fgets(cmd,N,stdin) == NULL)
		{
			printf("Fgets Error!\n");
			return -1;
		}
		
		
		cmd[strlen(cmd) - 1] = '\0';
		
		if(strncmp(cmd,"help",4) == 0)
		{
			proc_menu();
		}
		else if(strncmp(cmd,"exit",4) == 0)
	    {
			proc_exit(addr);
			exit(0);
		}
		else if(strncmp(cmd,"ls",2) == 0)
		{
			proc_ls(addr,cmd);
		}
		else if(strncmp(cmd,"get",3) == 0)
		{
			proc_get(addr,cmd);
		}
		else if(strncmp(cmd,"put",3) == 0)
		{
			proc_put(addr,cmd);
		}
		else
		{
			printf("command is error!please try again!\n");
		}
	}
	
	return 0;
}

int parse(char *buf,char **args)
{
	int num = 0;
	
	while(*buf != '\0')
	{
      while((*buf == ' ')||(*buf == '\t'||(*buf == '\n')))
		  *buf++ = '\0';
	    *args++=buf;
		++num;
	  while((*buf!='\0')&&(* buf!=' ')&&(*buf!='\t')&&(*buf!='\n'))
		  buf++;
	  
	}
	
	*args = '\0';
	return num;
		
}

void proc_menu()
{
	
	printf("\n-----------------------------------------------\n");
	printf("|  help:show all commands                       |\n");
	printf("|  exit:exit                                    |\n");
	printf("|  ls:show the file name list on server         |\n");
	printf("|  get filename:download file on server         |\n");
	printf("|  put filename:upload file on server           |\n");
	printf("-------------------------------------------------\n");
	
	
	return ;
}


void proc_exit(struct sockaddr_in addr)
{
	int sockfd;
	printf("Byte!\n");
	
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		printf("socket error!\n");
		exit(1);
	}
	
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
	{
		printf("connect error!\n");
		exit(1);
	}
	if(write(sockfd,"exit",N) < 0)
	{
		printf("write error!\n");
		exit(1);
	}
	
	close(sockfd);
	return;
}

void proc_ls(struct sockaddr_in addr,char *cmd)
{
	int sockfd;
	
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		printf("socket error!\n");
		exit(1);
	}
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
	{
		printf("connet error!\n");
		exit(1);
	}
	if(write(sockfd,cmd,N) < 0)
	{
		printf("write error!\n");
		exit(1);
	}
	
	while(read(sockfd,cmd,N) > 0)
	{
		printf("%s",cmd);
	}
	
	printf("\n");
	close(sockfd);
	
	return ;
	
}



void proc_get(struct sockaddr_in addr,char *cmd)
{
	int fd;
	int sockfd;
	char buffer[N];
	int nbytes;
	char *cmds[64];
	int cmdnum;
	
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		printf("socket error!\n");
		exit(1);
	}
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
	{
		printf("connet error!\n");
		exit(1);
	}
	if(write(sockfd,cmd,N) < 0)
	{
		printf("write error!\n");
		exit(1);
	}
	
	if(read(sockfd,buffer,N) < 0)
	{
		printf("read error!\n");
		exit(1);
	}
	
	if(buffer[0] == 'N')
	{
		close(sockfd);
		printf("can't open file");
		return;
	}
	cmdnum = parse(cmd,cmds);
	
	if((fd = open(cmds[1],O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
	{
		printf("open error!\n");
		exit(1);
	}
	while((nbytes = read(fd,buffer,N)) > 0)
	{
		if(write(sockfd,buffer,nbytes) < 0)
		{
			perror("proc_get get2");
		}
	}
	
	close(fd);
	close(sockfd);
	
    return ;
	
	
}

void proc_put(struct sockaddr_in addr,char *cmd)
{
	int fd;
	int sockfd;
	char buffer[N];
	int nbytes;
	char *cmds[64];
	int cmdnum;
	
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		printf("socket error!\n");
		exit(1);
	}
	if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
	{
		printf("connet error!\n");
		exit(1);
	}
	if(write(sockfd,cmd,N) < 0)
	{
		printf("write error!\n");
		exit(1);
	}
	
   cmdnum = parse(cmd,cmds);
	
	
	if((fd = open(cmds[1],O_RDONLY,0644)) < 0)
	{
		
		printf("open error!\n");
		exit(1);
	}
	while((nbytes = read(fd,buffer,N)) > 0)
	{
		if(write(sockfd,buffer,nbytes) < 0)
		{
			perror("proc_get put2");
		}
	}
	
	close(fd);
	close(sockfd);
	
    return ;
	
	
}

Makefile

DIR_SERVER=./serverfolder
DIR_CLIENT=./clientfolder
SP=$(DIR_SERVER)/server
C=$(DIR_CLIENT)/client
all:$(SP) $(C)
$(SP):$(SP).c
	gcc $^ -o $@
$(C):$(C).c
	gcc $^ -o $@
clean:
	rm -f $(SP)  $(C)

测试

java io传输压缩包损坏_#include