socket编程-客户端向服务器发送字符串,传文件

功能:分为客户端和服务器,client可向server传送字符串,传送文件。

环境:Ubuntu
编译方法: server.c: gcc  –o server server.c
client.c:  gcc -o client client.c
运行方法:打开两个终端,先在一个终端运行./ server,然后在另一个终端运行 ./client。
源码:
server.c
#include<stdio.h>

#include<unistd.h>

#include<stdlib.h>

#include<string.h>

#include<sys/socket.h>

#include<sys/stat.h>

#include<arpa/inet.h>

#define MAXBUF 256

#define PORT 7787

int main()

{

    int clen;

    int ssock,csock;

    struct sockaddr_in client_addr,server_addr;//客户端,服务器地址

    char buf[MAXBUF+5], name[MAXBUF+5];//两个缓冲区

    FILE *fp;

    if((ssock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)

    /*  AF_UNIX表示只能够用于单一的Unix 系统进程间通信,SOCK_STREAM表明用的是TCP 协议

    成功时返回文件描述符,失败时返回-1

    */

        {

            perror("socket error:");

            exit(1);

        }

    clen = sizeof(client_addr);

    memset(&server_addr,0,sizeof(server_addr));

    /*将已开辟的server_addr的前sizeof(server_addr)个字节设置为0 */

    server_addr.sin_family     =AF_INET;
    /*sin_family指代协议族,在socket编程中只能是AF_INET*/

    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    /*INADDR_ANY表示可以和任何的主机通信*/

    server_addr.sin_port=htons(PORT);/*sin_port存储端口号*/

    if(bind(ssock,(struct sockaddr *)&server_addr,sizeof(server_addr))<0){

      /*  使用bind进行绑定端口: bind将本地的端口同socket返回的文件描述符捆绑在一起.

      成功是返回0,失败返回-1

      */

        perror("bind error");

        exit(1);

    }

    if(listen(ssock,8)<0){

      /*  listen(bind后的文件描述符,最大请求排队长度)

      listen函数将bind的文件描述符变为监听套接字,成功返回0,否则返回-1

      */

        perror("listen error:");

        exit(1);

    }

    csock=accept(ssock,(struct sockaddr *)&client_addr,(socklen_t*)&clen);

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

      addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了

      accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了

      失败时返回-1

      */

    while(1){

        if(recv(csock,buf, MAXBUF,MSG_WAITALL)>0)

        //MSG_WAITALL表示没有读到指定字节数之前不返回

    {

        if(strcmp(buf,"@#$%")==0){//表示要传文件

        recv(csock,buf,MAXBUF,MSG_WAITALL);//接收文件名

        sprintf(name,"%s1",buf);//将buf格式化为长字符串型,赋给name

            if((freopen(name,"w",stdout))!=NULL){//以写方式打开文件

            while(recv(csock,buf,MAXBUF,MSG_WAITALL)>0)//接收文件内容

            {

                if(strcmp(buf,"@#$%")==0)break;//收到@#$%表示已经传送完毕

                fwrite(buf,sizeof(char),strlen(buf),stdout);//写入文件

            }

            fclose(stdout);

            freopen("/dev/tty","w",stdout);//

            puts("File received success!");

        }

        }

        else if(strcmp(buf,"%$#@")==0){//表示传字符

                recv(csock,buf,MAXBUF,MSG_WAITALL);//接收传来的字符

                printf("%s\n",buf);

                send(csock,"Server receive message success!",MAXBUF,0);//返回确认信息

        }

    }

    }

    close(csock);

    return 0;

}

 

 client.c
#include<stdio.h>

#include<unistd.h>

#include<stdlib.h>

#include<sys/socket.h>

#include<sys/stat.h>

#include<arpa/inet.h>

#include<string.h>

#define MAXBUF 256

#define PORT 7787

int main()

{

    int ssock;

    int clen, ch;

    char buf[MAXBUF+5];//缓冲区

    struct sockaddr_in server_addr;



    if((ssock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0){

        // 建立socket,使用因特网,TCP流传输

        perror("socket error:");

        exit(1);

    }

    clen = sizeof(server_addr);

    memset(&server_addr,0,sizeof(server_addr));

    server_addr.sin_family     =AF_INET;

    server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");

    //inet_addr:ip转换为4字节整形,使用时需要根据服务端ip进行更改

    server_addr.sin_port =htons(PORT);

    if(connect(ssock,(struct sockaddr *)&server_addr,clen)<0){

            /*  客户端连接服务器,参数依次为socket文件描述符,地址信息,地址结构大小,

            connect函数是客户端用来同服务端连接的.成功时返回0, 失败返回-1

            */

            perror("connect error:");

            exit(1);

    }

    while(1)

    {

    printf("1: Send Message\n2: Send File\n3: Exit [1/2/3]?");

    scanf("%d",&ch);

    if(ch==1){//Send Message

        scanf("%s",buf);

        send(ssock,"%$#@",MAXBUF,0);//告诉服务器要传字符串

        send(ssock, buf, MAXBUF,0);//发送要传的字符

        recv(ssock, buf, MAXBUF,MSG_WAITALL);//接收确认信息

        puts(buf);

    }

    else if(ch==2){//Send File

        printf("input the filename: ");

        scanf("%s",buf);

        if(freopen(buf, "r",stdin)!=NULL){

            send(ssock,"@#$%",MAXBUF,0);//告诉服务器要传文件

            send(ssock,buf,MAXBUF,0);//传文件名

            int cnt=0;

            while((ch=getchar())!=EOF){

                buf[cnt++]=ch;//buf缓冲区大小为MAXBUF,也就是每读MAXBUF个字符,传送一次

                if(cnt==MAXBUF){

                    buf[cnt]=0,cnt=0;

                    send(ssock,buf,MAXBUF,0);

                }

            }

            if(cnt){buf[cnt]=0,cnt=0;send(ssock,buf,MAXBUF,0);}//传送最后不足MAXBUF的部分

            send(ssock,"@#$%",MAXBUF,0);//表示传送完毕

            fclose(stdin);

            freopen("/dev/tty","r",stdin);

        }

    }

    else break;

    }

    close(ssock);

    return 0;

}

 

posted @ 2014-12-15 15:36  云裳诉  阅读(1779)  评论(0编辑  收藏  举报