客户端与服务器端通信流程

客户端Linux
    建立socket
    确定服务器scokaddr_in结构体
        点分十进制IP转换
    使用connect连接
    打开文件
    准备缓冲区
    缓冲区初始化置空
    将文件内容读入缓冲区
    使用send将缓冲区内容发送到服务器
    文件内容发送完成
    关闭文件
    关闭socket
服务器 Windows

    添加winsock头文件
    初始化WSAStartup 
    建立socket
    确定服务器scokaddr_in结构体
        点分十进制IP转换
    使用bind绑定套接字
    使用listen监听
    使用accept接受连接请求
        accept返回新的套接字描述符
    使用recv接收传来的数据(文件路径)
    打开文件,这里需要文件名
        从该字符串获取文件名
    使用recv接收文件内容
        判断recv函数返回的状态
    将接收到的内容放入缓冲区
    将缓冲区内容写入文件
    关闭文件
    WSACleanup函数
    关闭socket

WINDOW下socket编程和LINUX的区别

头文件

    #include <winsock2.h>

初始化

    windows下需要用WSAStartup启动Ws2_32.lib,并且要用#pragma comment(lib,"Ws2_32")来告知编译器链接该lib。linux下不需要

使用Socket的程序在使用Socket之前必须调用WSAStartup函数。

    int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ); 

    1)wVersionRequested是Windows Sockets API提供的调用方可使用的最高版本号。
    2)lpWSAData 是指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。
    当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。假如一个程序要使用2.1版本的Socket,那么程序代码如下 
        wVersionRequested = MAKEWORD( 2, 1 ); 
WSACleanup函数 

    int WSACleanup (void); 
    应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统
关闭socket

    windows下closesocket(...)
    linux下close(.…

获取错误码
    windows下getlasterror()/WSAGetLastError()
    linux下,未能成功执行的socket操作会返回-1;如果包含了errno.h,就会设置errno变量

LINUX和WINDOWS下sockaddr_in结构体的区别

Linux:
    struct sockaddr_in 
    { 
    u_short   sin_family;//2B
    u_short    sin_port;//2B
    struct in_addr   sin_addr;//4B
    char   sin_zero[8];//8B
    } 
Windows:
    struct SOCKADDR_IN {
short int          sin_family; //2B
        unsigned short int sin_port;    //2B端口(使用网络字节顺序)
struct IN_ADDR   sin_addr;    //4B IP地址,是个结构
unsigned char      sin_zero[8]; //8B
                             };

其他的一些小细节

在Windows中
    bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)
在Linux中
    connect(sockcd,(struct sockaddr*)&server,sizeof(server))
在C和C++中文件的创建函数是不一样的,不要弄错了

Windows和Linux中的sleep函数
    Windows中Sleep函数S大写,Linux中sleep函数s小写
    Windows中头文件是#include <windows.h>
    Linux中头文件是#include <unistd.h>

Linux中将IP地址赋值给IP地址结构体
    if(inet_pton(AF_INET,"192.168.0.13",&server.sin_addr)<0)
        {
            printf("inet_pton error!\n");
        }
Windows中赋值
    server.sin_addr.s_addr= inet_addr("192.168.0.13");

WINDOWS作为服务器端的代码

#include <winsock2.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


#pragma comment(lib, "WS2_32.lib")          //add ws2_32.lib

#define MAXLINE 4096
#define BUFFER_SIZE 1024

int main()
{

    WORD    wVersionRequested;
    WSADATA wsaData;
    int     err,iLen;
    SOCKET sockSrv;
    wVersionRequested   =   MAKEWORD(2,2);

    char filename[100];
    char filepath[100];

    char *buffer;//file buffer
    int fileTrans;
    int lenfilepath;
    FILE *fp;
    int writelength;

    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    //bzero(buffer,BUFFER_SIZE);
    memset(buffer,0,sizeof(buffer));

    if(WSAStartup(wVersionRequested,&wsaData)!=0)
    {
        printf("WSAStartup error!\n");
        return -1;
    }

    if(( sockSrv =socket(AF_INET,SOCK_STREAM,0))<0){
        printf("socket error!\n");
        return -2;
    }
    SOCKADDR_IN addrSrv;
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);
    addrSrv.sin_port = htons(9000);

    if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))!=0)
    {

        printf("bind error!\n");
        return -3;
    }

    if(listen(sockSrv,5)!=0)
    {

        printf("listen error!\n");
        return -4;
    }
    printf("Sever build finished ...\n");

    while(1)
    {
        SOCKET temp;
        if((temp = accept(sockSrv,(SOCKADDR*)NULL,NULL))>0)
        {
            //printf("client IP:   %d\n",ntohl(client.sin_addr.s_addr));
            //printf("client PORT: %d\n",ntohs(client.sin_port));

            memset(filename,'\0',sizeof(filename));
            memset(filepath,'\0',sizeof(filepath));

            lenfilepath = recv(temp,filepath,100,0);
            printf("filepath :%s\n",filepath);
            if(lenfilepath<0)
            {
                printf("recv error!\n");
            }
            else
            {
                int i=0,k=0;
                for(i=strlen(filepath);i>=0;i--)
                {
                    if(filepath[i]!='/')
                    {
                        k++;
                    }
                    else
                        break;
                }
                strcpy(filename,filepath+(strlen(filepath)-k)+1);
            }
            printf("filename :%s\n",filename);
            fp = fopen(filename,"w");
            if(fp!=NULL)
            {
                while(fileTrans =recv(temp,buffer,BUFFER_SIZE,0))
                {
                    if(fileTrans<0)
                    {
                        printf("recv error!\n");
                        break;
                    }
                    writelength = fwrite(buffer,sizeof(char),fileTrans,fp);
                    if(writelength <fileTrans)
                    {
                        printf("write error!\n");
                        break;
                    }
                    //bzero(buffer,BUFFER_SIZE);
                    memset(buffer,'\0',sizeof(buffer));
                }
                printf("recv finished!\n");
                fclose(fp);
            }
            else
            {
                printf("filename is null!\n");

            }
            closesocket(temp);


        }
        else
        {
            printf("accept error!\n");
            closesocket(temp);
        }
    }
    closesocket(sockSrv);
    WSACleanup();
    return 0;

}

LINUX作为客户端的代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <memory.h> 
#include <stdlib.h>  //for malloc

#define BUFFER_SIZE 1024

int main()
{
    int sockcd;
    struct sockaddr_in server;
    char filepath[100];//file to translate

    FILE *fp;
    int lenpath; //filepath length
    char *buffer;//file buffer
    int fileTrans;
    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    bzero(buffer,BUFFER_SIZE); 
    //memset(buffer,0,sizeof(buffer));

    if((sockcd = socket(AF_INET,SOCK_STREAM,0))<0)
    {
        printf("socket build error!\n");
    }
    memset(&server,0,sizeof(server));
    server.sin_family= AF_INET;
    server.sin_port = htons(9000);
    if(inet_pton(AF_INET,"192.168.0.13",&server.sin_addr)<0)
    {
        printf("inet_pton error!\n");
    }

    if(connect(sockcd,(struct sockaddr*)&server,sizeof(server))<0)
    {
        printf("connect error!\n");
    }//connect with server 

    printf("file path:\n");
    scanf("%s",filepath);//get filepath

    fp = fopen(filepath,"r");//opne file
    if(fp==NULL)
    {
        printf("filepath not found!\n");
        return 0;

    }
    printf("filepath : %s\n",filepath);
    lenpath = send(sockcd,filepath,strlen(filepath),0);// put file path to sever 
    if(lenpath<0)
    {
        printf("filepath send error!\n");
    }
    else
    {
        printf("filepath send success!\n");
    }
    sleep(3);
    while((fileTrans = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0)
    {
        printf("fileTrans =%d\n",fileTrans);
        if(send(sockcd,buffer,fileTrans,0)<0)
        {
            printf("send failed!\n");
            break;      
        }
        bzero(buffer,BUFFER_SIZE); 
        //memset(buffer,0,sizeof(buffer));  
    }
    fclose(fp);

    close(sockcd);



    return 0;
}

更多推荐

WINDOW与LINUX的TCP/IP通信