推荐资料的话,《unix网络编程》这本书很好,公认的经典,当教科书用,这本书里有你想要的所有内容。
ps:你基础太差,多补补吧,别想一下吃个胖子。
另外我这里正好有个例子满足你的要求,贴给你,自己写的,不是网上找的,用的是多进程加I/O复用技术:
server端:
/****************************************************************
**
**
**
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#define BUFLEN 1024
#define MAX(a,b) ((a)>(b)?(a):(b))
typedef void Sigfunc (int)
void str_echo(FILE *,int)
//Sigfunc *signal(int, Sigfunc *)
int main(int argc,char **argv)
{
int connfd,listenfd
pid_t childpid
socklen_t clilen
struct sockaddr_in cliaddr,servaddr
void sig_chld(int)
listenfd = socket(AF_INET, SOCK_STREAM, 0)
memset(&servaddr,0,sizeof(servaddr))
servaddr.sin_family = AF_INET
servaddr.sin_addr.s_addr = htonl(INADDR_ANY)
servaddr.sin_port = htons(5358)
bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))
listen(listenfd,8)
signal(SIGCHLD,sig_chld)
while(1)
{
clilen = sizeof(cliaddr)
if((connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen)) <0)
{
if(errno == EINTR)
{
fputs("accept error: EINTR\n",stdout)
continue
}
else
{
fputs("accept error..\n",stdout)
}
}
if((childpid = fork()) == 0)
{
close(listenfd)
str_echo(stdin,connfd)
exit(0)
}
close(connfd)
}
}
void str_echo(FILE *fp,int sockfd)
{
int n = 0
char sendbuf[BUFLEN] = { 0 },recvbuf[BUFLEN] = { 0 }
int maxfdp
fd_set rset
FD_ZERO(&rset)
while(1)
{
FD_SET(fileno(fp),&rset)
FD_SET(sockfd, &rset)
maxfdp = MAX(fileno(fp),sockfd)+1
select(maxfdp, &rset ,NULL, NULL, NULL)
if(FD_ISSET(sockfd, &rset))
{
if(n = read(sockfd, recvbuf, BUFLEN) == 0)
{
return
}
if(n == -1)
{
break
}
printf("%s\n",recvbuf)
memset(recvbuf,0,BUFLEN)
}
if(FD_ISSET(fileno(fp),&rset))
{
scanf("%s",sendbuf)
write(sockfd, sendbuf,strlen(sendbuf))
}
}
}
void sig_chld (int signo)
{
pid_t pid
int stat
while ((pid = waitpid(-1,&stat, WNOHANG)) >0)
{
printf("child %d terminated\n",pid)
}
return
}
client端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
int s,connectReturn, maxfd
fd_set rset
char sendbuf[1024] = {0}
char recvbuf[1024] = {0}
long port=5358
s=socket(PF_INET,SOCK_STREAM,0)
struct sockaddr_in sa
sa.sin_family=AF_INET
sa.sin_addr.s_addr=inet_addr("127.0.0.1")
sa.sin_port=htons(port)
connectReturn=connect(s,(struct sockaddr *)&sa,sizeof(sa))
printf("%d\n",connectReturn)
FD_ZERO(&rset)
while(1)
{
FD_SET(fileno(stdin), &rset)
FD_SET(s, &rset)
maxfd=MAX(fileno(stdin), s) + 1
select(maxfd, &rset, NULL, NULL, NULL)
if(FD_ISSET(fileno(stdin), &rset))
{
scanf("%s",sendbuf)
send(s,sendbuf,strlen(sendbuf),0)
bzero(sendbuf, 1024)
}
else if(FD_ISSET(s, &rset))
{
memset(recvbuf,0,1024)
recv(s,recvbuf,1024,0)
printf("remote: %s\n",recvbuf)
}
}
return 0
}
这要你的通信程序协商一个协议,比如定义一个通信结构体,传文件的时候,一开始发送结构体的信息过去,告诉对端你的文件总大小,然后,传输过程中,统计已经收到或者发送的数据,做个除法就得到速率了。具体这类协商,你可以自己随便想,也可以借鉴现有的比较好的一些设计,有些考虑断点续传的技术,还有压缩的,看你代码也不需要考虑吧。
客户端#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <errno.h>
#define SERVER_PORT_ID 6081
#define CLIENT_PORT_ID 6086
#define SERVER_HOST_ADDR "128.119.40.186"
/* gaia.cs.umass.edu */
#define MAXSIZE 512
#define ACK 2
#define NACK 3
#define REQUESTFILE 100
#define COMMANDNOTSUPPORTED 150
#define COMMANDSUPPORTED 160
#define BADFILENAME 200
#define FILENAMEOK 400
#define STARTTRANSFER 500
int readn(int sd,char *ptr,int size)
int writen(int sd,char *ptr,int size)
main(int argc,char *argv[])
{
int sockid, newsockid,i,getfile,ack,msg,msg_2,c,len
int no_writen,start_xfer, num_blks,num_last_blk
struct sockaddr_in my_addr, server_addr
FILE *fp
char in_buf[MAXSIZE]
if(argc != 2)
no_writen = 0
num_blks = 0
num_last_blk = 0
len = strlen(argv[1])
printf("client: creating socket\n")
if ((sockid = socket(AF_INET,SOCK_STREAM,0)) < 0)
{ printf("client: socket error : %d\n", errno) exit(0)
}
printf("client: binding my local socket\n")
bzero((char *) &my_addr,sizeof(my_addr))
my_addr.sin_family = AF_INET
my_addr.sin_addr.s_addr = htonl(INADDR_ANY)
my_addr.sin_port = htons(CLIENT_PORT_ID)
if (bind(sockid ,(struct sockaddr *) &my_addr,sizeof(my_addr)) < 0)
{printf("client: bind error :%d\n", errno) exit(0)
}
printf("client: starting connect\n")
bzero((char *) &server_addr,sizeof(server_addr))
server_addr.sin_family = AF_INET
server_addr.sin_addr.s_addr = inet_addr(SERVER_HOST_ADDR)
server_addr.sin_port = htons(SERVER_PORT_ID)
if (connect(sockid ,(struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0)
{printf("client: connect error :%d\n", errno) exit(0)
}
/* Once we are here, we've got a connection to the server */
/* tell server that we want to get a file */
getfile = htons(REQUESTFILE)
printf("client: sending command request to ftp server\n")
if((writen(sockid,(char *)&getfile,sizeof(getfile))) < 0)
/* want for go-ahead from server */
msg = 0
if((readn(sockid,(char *)&msg,sizeof(msg)))< 0)
msg = ntohs(msg)
if (msg==COMMANDNOTSUPPORTED) {
printf("client: server refused command. goodbye\n")
exit(0)
}
else
printf("client: server replied %d, command supported\n",msg)
/* send file name to server */
printf("client: sending filename\n")
if ((writen(sockid,argv[1],len))< 0)
/* see if server replied that file name is OK */
msg_2 = 0
if ((readn(sockid,(char *)&msg_2,sizeof(msg_2)))< 0)
msg_2 = ntohs(msg_2)
if (msg_2 == BADFILENAME) {
printf("client: server reported bad file name. goodbye.\n")
exit(0)
}
else
printf("client: server replied %d, filename OK\n",msg_2)
/* CLIENT KNOWS SERVER HAS BEEN ABLE TO OPEN THE FILE IN READ
MODE AND IS ASKING FOR GO-AHEAD*/
/* CLIENT NOW OPENS A COPY OF THE FILE IN WRITE MODE AND SENDS
THE GOAHEAD TO SERVER*/
printf("client: sending start transfer command\n")
start_xfer = STARTTRANSFER
start_xfer = htons(start_xfer)
if ((writen(sockid,(char *)&start_xfer,sizeof(start_xfer)))< 0)
{printf("client: write error :%d\n", errno) exit(0)
}
if ((fp = fopen(argv[1],"w")) == NULL)
/*NOW THE CLIENT IS READING INFORMATION FROM THE SERVER REGARDING HOW MANY
FULL BLOCKS OF SIZE MAXSIZE IT CAN EXPECT. IT ALSO RECEIVES THE NUMBER
OF BYTES REMAINING IN THE LAST PARTIALLY FILLED BLOCK, IF ANY */
if((readn(sockid,(char *)&num_blks,sizeof(num_blks))) < 0)
num_blks = ntohs(num_blks)
printf("client: server responded: %d blocks in file\n",num_blks)
ack = ACK
ack = htons(ack)
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0)
{printf("client: ack write error :%d\n",errno)exit(0)
}
if((readn(sockid,(char *)&num_last_blk,sizeof(num_last_blk))) < 0)
num_last_blk = ntohs(num_last_blk)
printf("client: server responded: %d bytes last blk\n",num_last_blk)
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0)
{printf("client: ack write error :%d\n",errno)exit(0)
}
/* BEGIN READING BLOCKS BEING SENT BY SERVER */
printf("client: starting to get file contents\n")
for(i= 0 i < num_blks i ++) {
if((readn(sockid,in_buf,MAXSIZE)) < 0)
no_writen = fwrite(in_buf,sizeof(char),MAXSIZE,fp)
if (no_writen == 0)
if (no_writen != MAXSIZE)
/* send an ACK for this block */
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0)
printf(" %d...",i)
}
/*IF THERE IS A LAST PARTIALLY FILLED BLOCK, READ IT */
if (num_last_blk > 0) {
printf("%d\n",num_blks)
if((readn(sockid,in_buf,num_last_blk)) < 0)
no_writen = fwrite(in_buf,sizeof(char),num_last_blk,fp)
if (no_writen == 0)
if (no_writen != num_last_blk)
if((writen(sockid,(char *)&ack,sizeof(ack))) < 0)
}
else printf("\n")
/*FILE TRANSFER ENDS. CLIENT TERMINATES AFTER CLOSING ALL ITS FILES
AND SOCKETS*/
fclose(fp)
printf("client: FILE TRANSFER COMPLETE\n")
close(sockid)
}
/* DUE TO THE FACT THAT BUFFER LIMITS IN KERNEL FOR THE SOCKET MAY BE
REACHED, IT IS POSSIBLE THAT READ AND WRITE MAY RETURN A POSITIVE VALUE
LESS THAN THE NUMBER REQUESTED. HENCE WE CALL THE TWO PROCEDURES
BELOW TO TAKE CARE OF SUCH EXIGENCIES */
int readn(int sd,char *ptr,int size)
{ int no_left,no_read
no_left = size
while (no_left > 0)
{ no_read = read(sd,ptr,no_left)
if(no_read <0) return(no_read)
if (no_read == 0) break
no_left -= no_read
ptr += no_read
}
return(size - no_left)
}
int writen(int sd,char *ptr,int size)
{ int no_left,no_written
no_left = size
while (no_left > 0)
{ no_written = write(sd,ptr,no_left)
if(no_written <=0) return(no_written)
no_left -= no_written
ptr += no_written
}
return(size - no_left)
}
服务端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <errno.h>
#define MY_PORT_ID 6081
#define MAXLINE 256
#define MAXSIZE 512
#define ACK 2
#define NACK 3
#define REQUESTFILE 100
#define COMMANDNOTSUPPORTED 150
#define COMMANDSUPPORTED 160
#define BADFILENAME 200
#define FILENAMEOK 400
int writen(int sd,char *ptr,int size)
int readn(int sd,char *ptr,int size)
main() {
int sockid, newsd, pid, clilen
struct sockaddr_in my_addr, client_addr
printf("server: creating socket\n")
if ((sockid = socket(AF_INET,SOCK_STREAM,0)) < 0)
printf("server: binding my local socket\n")
bzero((char *) &my_addr,sizeof(my_addr))
my_addr.sin_family = AF_INET
my_addr.sin_port = htons(MY_PORT_ID)
my_addr.sin_addr.s_addr = htons(INADDR_ANY)
if (bind(sockid ,(struct sockaddr *) &my_addr,sizeof(my_addr)) < 0)
printf("server: starting listen \n")
if (listen(sockid,5) < 0)
while(1==1) {
/* ACCEPT A CONNECTION AND THEN CREATE A CHILD TO DO THE WORK */
/* LOOP BACK AND WAIT FOR ANOTHER CONNECTION */
printf("server: starting accept\n")
if ((newsd = accept(sockid ,(struct sockaddr *) &client_addr,
&clilen)) < 0)
printf("server: return from accept, socket for this ftp: %d\n",
newsd)
if ( (pid=fork()) == 0) {
/* CHILD PROC STARTS HERE. IT WILL DO ACTUAL FILE TRANSFER */
close(sockid) /* child shouldn't do an accept */
doftp(newsd)
close (newsd)
exit(0) /* child all done with work */
}
/* PARENT CONTINUES BELOW HERE */
close(newsd)/* parent all done with client, only child */
} /* will communicate with that client from now on */
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)