简要介绍一下代码结构:
~project-----------fileclient.c
~ |-----------fileserver.c
~ |-----------Makefile
~ |-----------common-----------common.c
~ |-----------common.h
编译方法: 进入project目录,make(有兴趣的话可以看看我的Makefile,其实写的不通用)
使用方法: 接收端运行 ./fileserver
发送端运行 ./fileclient <localfile> <serverIP>
如果谁愿意读此代码,请重点读fileserver.c 和 fileclient.c ,通信交互部分我用
"/ communication part /"的方式隔开了, common 目录下的 common.h 主要定义了一些wrapper functions ,在内部进行错误处理,让主函数调用起来更简洁;另外还定义了一些常量如服务器端口号和应用层缓冲区大小。
此代码实现的协议很简单,不过由于用的LINUX的SOCKET实现,不能运行在WINDOWS上,不过说要是能做出对应project的WINDOWS版本,那么就完成了协议的跨平台实现,LINUX和WIN也可以互相传文件了;不过我不熟悉WINDOWS和WINSOCK的调用,谁能做出来的话,能把代码给我吗?万分感激!
。。。。。。。。
代码格式都变了,汗!居然不让我在前面放空格。
要看的人可以用 indent -kr <cfile>来格式化一下。(前提是要装indent)
fileclient.c
#include "common/common.h"
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "Usage: ./fileclient <file> <serverIP>/n");
exit(1);
}
int sockfd;
char buff[BUFFERSIZE + 1];
char filenameheader[BUFFERSIZE + 1];
struct sockaddr_in servaddr;
int filefd; /* file descriptor */
int count;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
Inet_pton(AF_INET, argv[2], &servaddr.sin_addr);
servaddr.sin_port = htons(PORT);
//
printf("connecting......../n");
Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
printf("transferring file name: %s......../n", argv[1]);
memcpy(filenameheader, argv[1], strlen(argv[1]));
filenameheader[strlen(argv[1])] = '/n';
filenameheader[strlen(argv[1]) + 1] = 0;
writen(sockfd, filenameheader, strlen(filenameheader));
printf("will transfer file: %s/n", argv[1]);
filefd = open(argv[1], O_RDONLY);
if (filefd < 0) {
fprintf(stderr, "can't open the file: %s/n", argv[1]);
exit(1);
}
while(count = read(filefd, buff, BUFFERSIZE)) {
if (count < 0) {
fprintf(stderr, "filefd read error/n");
exit(1);
}
if (writen(sockfd, buff, count) < 0) {
fprintf(stderr, "writing to sockfd error/n");
exit(1);
}
}
Close(filefd);
Close(sockfd);
printf("file %s transferred!/n", argv[1]);
//
return 0;
}
______________________________________________________________________-
fileserver.c
#include "common/common.h"
int main(void)
{
int listenfd, connfd;
char buff[BUFFERSIZE + 1];
char filename[BUFFERSIZE + 1];
struct sockaddr_in servaddr, cliaddr;
int cliaddrlen;
int filefd; /* file descriptor */
int count;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
//
while(1) {
printf("listening......../n");
cliaddrlen = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
printf("readinging filename......../n");
if (readline(connfd, buff, BUFFERSIZE) < 0) {
fprintf(stderr, "readline error/n");
exit(1);
}
buff[strlen(buff) - 1] = 0; /* change '/n' to NUL */
memcpy(filename, buff, BUFFERSIZE + 1);
printf("will save to file: %s/n", buff);
filefd = open(buff, O_WRONLY | O_CREAT);
if (filefd < 0) {
fprintf(stderr, "can't open the file: %s/n", buff);
exit(1);
}
while(count = read(connfd, buff, BUFFERSIZE)) {
if (count < 0) {
fprintf(stderr, "connfd read error/n");
exit(1);
}
if (writen(filefd, buff, count) < 0) {
fprintf(stderr, "writing to filefd error/n");
exit(1);
}
}
Close(filefd);
Close(connfd);
printf("file %s received!/n", filename);
}
Close(listenfd);
//
return 0;
}
common/common.h
#ifndef _COMMON_H
#define _COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#define LISTENQ 20
#define MAXLINE 40
#define BUFFERSIZE 4096
#define PORT 50000
ssize_t writen(int fd, const void * vptr, size_t n);
ssize_t readline(int fd, void * vptr, size_t maxlen);
//wrappers
int Socket(int domain, int type, int protocol);
int Accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen);
int Inet_pton(int af, const char *src, void *dst);
int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int Listen(int sockfd, int backlog);
int Close(int fd);
sig_t Signal(int signum, sig_t handler);
#endif
__________________________________________________________
common.c
#include "common.h"
ssize_t writen(int fd, const void * vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char * ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR) {
nwritten = 0;
} else {
return -1;
}
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
ssize_t readline(int fd, void * vptr, size_t maxlen)
{
ssize_t n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < maxlen; n++) {
again:
if ((rc = read(fd, &c, 1)) == 1) {
*ptr++ = c;
if (c == '/n') {
break;
}
} else if (rc == 0) { /* EOF */
*ptr = 0;
return (n - 1);
} else {
if (errno == EINTR) {
goto again;
}
return (-1);
}
}
*ptr = 0;
return (n);
}
int Socket(int domain, int type, int protocol)
{
int sockfd;
if ((sockfd = socket(domain, type, protocol)) < 0) {
fprintf(stderr, "socket error/n");
exit(1);
}
return sockfd;
}
int Accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen)
{
int ret;
if ((ret = accept(sockfd, addr, addrlen)) < 0) {
fprintf(stderr, "accept error/n");
exit(1);
}
return ret;
}
int Inet_pton(int af, const char *src, void *dst)
{
int ret;
if ((ret = inet_pton(af, src, dst)) < 0) {
fprintf(stderr, "inet_pton error for %s/n", src);
exit(1);
}
return ret;
}
int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
int ret;
if ((ret = connect(sockfd, addr, addrlen)) < 0) {
fprintf(stderr, "connect error/n");
exit(1);
}
return ret;
}
int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
int ret;
if ((ret = bind(sockfd, addr, addrlen)) < 0) {
fprintf(stderr, "bind error/n");
exit(1);
}
return ret;
}
int Listen(int sockfd, int backlog)
{
int ret;
if ((ret = listen(sockfd, backlog)) < 0) {
fprintf(stderr, "listen error/n");
exit(1);
}
return ret;
}
int Close(int fd)
{
int ret;
if ((ret = close(fd)) < 0) {
fprintf(stderr, "close error/n");
exit(1);
}
return ret;
}
sig_t Signal(int signum, sig_t handler)
{
struct sigaction act, oact;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(signum, &act, &oact) < 0) {
return (SIG_ERR);
}
return (oact.sa_handler);
}
__________________________________________________________
Makefile
CC=gcc
PROG_NAME=fileclient fileserver # ELF文件
INCS=common/common.h
SRCS=fileclient.c fileserver.c # C文件
# 从 .c 文件到 .o 文件
OBJS=${SRCS:.c=.o}
# libs
LIBS=
# ---- 用户修改区域结束
# _________________________________________________
all:${PROG_NAME}
fileclient:fileclient.o common/common.o
${CC} -o $@ $^
fileserver:fileserver.o common/common.o
${CC} -o $@ $^
# 如果有头文件进行修改,则自动编译源文件
${OBJS}:${INCS}
.c.o:
${CC} -c $< -Icommon
common/common.o:common/common.c common/common.h
cd common && ${CC} -c common.c
clean:
rm -f *.o ${PROG_NAME} common/*.o
rebuild:clean all