Socket——最基本的TCP CS结构的程序

该例子完成了一个基本用TCP实现的CS程序,支持大文件传输,Client可以向Server发送要下载文件的名字,Server支持Client完成下载,并显示进度。该例子并没有文件的容错处理,也没有socket方面的各种异常的处理。 两个地方注意:1.TCP客户端和服务器端程序的基本结构                              2.文件的处理

Client:

#include <iostream>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <cerrno>

#include <unistd.h>

#include <cstring>

#include <fstream>

#define MAX_LEN 1024

#define MAX_SIZE 1024

using namespace std;

static int download_size = 0;



int main(int argc, char *argv[])

{

   int sockfd;

   int connfd;

   int ret_val = 0;

   struct sockaddr_in servaddr;

   string down_filename;//download filename

   string save_filename;//save filename



   //user input the argument

   if(argc != 5) {

      printf("Usage:./client <address> <port> <Download filename> <Save filename>/n");

      exit(1);

   }



   //inital the download and save file name

   down_filename = argv[3];

   save_filename = argv[4];



   //initial servaddr

   bzero(&servaddr,sizeof(servaddr));

   ret_val = inet_pton(AF_INET,argv[1],&servaddr.sin_addr);

   if(ret_val <= 0)

   {

     perror("inet_pton");

     return -1;

   }

   servaddr.sin_family = AF_INET;

   servaddr.sin_port = htons(atoi(argv[2]));



   //create socket

   sockfd = socket(AF_INET,SOCK_STREAM,0);

   if(sockfd == -1)

   {

     perror("socket");

     return -1;

   } 

   

   //connect

   socklen_t len_serv = sizeof(servaddr);

   connfd = connect(sockfd,(struct sockaddr *)&servaddr,len_serv);

   if(connfd < 0) {

     perror("Connect");

     return -1;

   }



   //send the command

   string command = down_filename;

   command += "/n/r";

   int num_bytes = 0;

   int ret_val_sent = 0;

   int len_send = command.length();

   while(num_bytes < len_send)

   {

       string send_buf = command.substr(num_bytes,len_send - num_bytes);

       ret_val_sent = send(sockfd,send_buf.c_str(),send_buf.length(),0);

	   if(ret_val_sent<0)

	   {

		   perror("send");

                                             return -1;

	   }

	   num_bytes += ret_val_sent;

   }



   //recv and save the file

   char buf[MAX_SIZE];

   int ret_val_save = 0;

   ofstream out(save_filename.c_str(),ios::out | ios::trunc | ios::binary);

   cout<<endl;

   if(!out.is_open())

   {

	   cout<<"Create file error:"<<save_filename<<endl;

	   return -1;

   }

   for(;;)

   {

	   ret_val_save = recv(sockfd,buf,MAX_SIZE,0);

	   if(ret_val_save < 0)

	   {

		   out.close();

		   return -1;

	   }

	   else if(ret_val_save > 0)//write

	   {

           out.write(buf, static_cast<streamsize>(ret_val_save));

	       download_size += ret_val_save;

           cout<<"Complete "<<download_size<<" bytes!"<<endl;

	   }

	   else if(ret_val_save == 0)

	   {

		   cout<<"Finished!"<<endl;

		   break;

	   }

   }

   cout<<endl;

   out.close();

   

   //close

   if(sockfd > 0)

	   close(sockfd);

 return 0;

}

 Server:

#include <cstdlib>

#include <cerrno>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <iostream>

#include <unistd.h>

#include <fstream>

#include <cstring>



#define BACKLOG 10

#define MAX_LEN 1024

#define MAX_SIZE 1024

using namespace std;



int main(int argc, char* argv[])

{

   int sockfd = 0;//for socket,bind,listen

   int connfd = 0;//for accept,send,recv

   struct sockaddr_in servaddr;

   struct sockaddr_in tempaddr;

   socklen_t temp_len;//using in bind,listen



   char ip_str[INET_ADDRSTRLEN];

   ssize_t number_bytes;

   string down_filename;

   string save_filename;

   int ret_val;

   

   //initial

   bzero(&servaddr,sizeof(servaddr));

   servaddr.sin_family = AF_INET;

   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

   servaddr.sin_port = 0;



   //socket,bind and listen

   sockfd = socket(AF_INET,SOCK_STREAM, 0);

   if(sockfd == -1)

   {

     perror("socket");

     exit(1);

   }

   ret_val = bind(sockfd,(const sockaddr*)&servaddr,sizeof(struct sockaddr));

   if(ret_val < 0)

   {

     perror("bind");

     exit(1);

   }

   //get localhost ip by getsockname, and then print it

   temp_len = sizeof(struct sockaddr);

   ret_val = getsockname(sockfd, (struct sockaddr *)&tempaddr,&temp_len);

   if(ret_val < 0)

   {

     perror("getsockname");

     return -1;

   }

   ret_val = listen(sockfd, BACKLOG);

   if(ret_val < 0)

   {

     perror("listen");

     return -1;

   }

   inet_ntop(AF_INET, &tempaddr.sin_addr, ip_str,INET_ADDRSTRLEN);

   cout<<"The host IP is: "<<ip_str<<". Please use this IP in Client!"<<endl;

   cout<<"The server is listening on port: "<<ntohs(tempaddr.sin_port)<<". Please use this Port in Client!"<<endl; 



   //the server run always

   while(1)

   {

      struct sockaddr_in cliaddr;

      socklen_t cli_len;

      cli_len = sizeof(cliaddr);

      bzero(&cliaddr,cli_len);

      connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&cli_len);

      //sockfd change to connfd

      if(connfd == -1)

      {

         perror("Accept");

         exit(1);

      }

   

      //get the command

      char line[MAX_SIZE];

      char cmd_buf[MAX_SIZE];

      int number_bytes = 0;

      char *ptr = 0;

      int read = 1;

      int recv_bytes = 0;

      memset(line, '/0', MAX_SIZE);

      memset(cmd_buf,'/0', MAX_SIZE);

	

	  //read command

      while(read)

      {   

		  recv_bytes = recv(connfd,line,MAX_SIZE,0);

		  if(ret_val_recv <0 )

		  {

			  perror("Recv");

		  }

		  line[recv_bytes] = '/0';

		  number_bytes += recv_bytes;

		  if ((ptr = strstr(line,"/n/r")) == 0)

		  {

			  if (number_bytes <= MAX_SIZE) 

				 strcat(cmd_buf, line);

          } 

          else

		  {

			  strncat(cmd_buf, line , ptr - line);

		      read = 0;

          }

	  }//while

	  //after while(read),get the down_filename

      down_filename = cmd_buf;

	  cout<<"The client requsts filename is: "<<down_filename<<endl;



	//read and send

	char buf_read[MAX_SIZE];

	int read_size = 0;

	ifstream in;

	in.open(down_filename.c_str(),ios::binary | ios::in);

	if(!in){

		cout<<"Cannot open the file"<<down_filename<<endl;

		return -1;

	}

	while(1)

	{

		int num_bytes = 0;

		in.read(buf_read, static_cast<streamsize>(MAX_SIZE));

		read_size = in.gcount();

		if(read_size < 0)

		{

			return -1;

		}

		else if(read_size == 0)

		{

			cout<<"Have finished transfer the file!"<<endl;

			break;

		}

		else 

	    {

			int len = read_size;

			int once_send_size = 0;

			while(num_bytes < read_size) 

			{

				once_send_size = send(connfd,buf_read + num_bytes,len,0);

				if (once_send_size < 0)

				{

					perror("send");

				}

				num_bytes += once_send_size;

				len -= once_send_size;

			}

	    }

	}//for

	in.close();

	close(connfd);

   }

   return 0;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值