回 帖 发 新 帖 刷新版面

主题:网络数据传输程序,请各位高手指点一下。不胜感激

4.    编写一个tcp服务器/客户端程序

要求:
1)    服务器监听指定的端口
2)    客户端连接服务器,发送如下格式请求
<起始数字>,<终止数字> ‘\n’
例如:
“10,20\n” 
3)    服务器收到后,返回起始数字到结束数字之间的整数,每行一个。例如:
10
11

20
4)    发送完毕服务器断开客户端连接
5)    客户端收到后,打印在标准输出上
6)    客户端关闭连接

回复列表 (共6个回复)

沙发


我也希望知道详情,望懂得的朋友教教,急啊!!

板凳

以下是我写的部分,但是不能正常运行,也找不到原因,请高手指点:
这是头文件


#ifndef COMDATA_H
#define COMDATA_H



#define MAX_PACKET_SIZE        10240            // 数据包的最大长度,单位是sizeof(char)
#define    MAXDATALENGTH        50                // 存放数据串的最大长度
#define    PORT                5555            // 端口号
#define SERVER_IP            "127.0.0.1"    // server端的IP地址

// 各种消息的宏定义
#define INVALID_MSG                    -1        // 无效的消息标识
#define MSG_DATA                    1        // 数据串
#define MSG_DATALENGTH                2        // 传送数据续列的长度
#define MSG_CLIENT_READY            3        // 客户端准备接收数据
#define MSG_SENDDATA                4        // 传送文件
#define MSG_SENDDATASUCCESS            5        // 传送文件成功

class CCSDef
{
public:
#pragma pack(1)                    // 使结构体的数据按照1字节来对齐,省空间

    // 消息头
    struct TMSG_HEADER
    {
        char    cMsgID;            // 消息标识

        TMSG_HEADER(char MsgID = INVALID_MSG)
            : cMsgID(MsgID)
        {
        }
    };

    // 收到客户端发送的,<起始数字>,<终止数字> ‘\n’,请求传送的数据串
    struct TMSG_DATA : public TMSG_HEADER
    {
        char dataBuf[50];        //保存传送的字符数组 
        TMSG_DATA(): TMSG_HEADER(MSG_DATA)
        {
        }
    };

    // 传送数据的长度
    struct TMSG_DATALENGTH : public TMSG_HEADER
    {
        long lLength;

        TMSG_DATALENGTH(long length)
            : TMSG_HEADER(MSG_DATALENGTH), lLength(length) 
        {

        }
    };

    // Client端已经准备好了,要求Server端开始传送文件
    struct TMSG_CLIENT_READY : public TMSG_HEADER
    {
        TMSG_CLIENT_READY(): TMSG_HEADER(MSG_CLIENT_READY)
        {
        }
    };
    
    // 传送数据
    struct TMSG_SENDDATA : public TMSG_HEADER
    {
        char dataBuf[50];
        TMSG_SENDDATA(): TMSG_HEADER(MSG_SENDDATA)
        {
        }
    };
    
    // 数据传送成功
    struct TMSG_SENDDATASUCCESS : public TMSG_HEADER
    {
        TMSG_SENDDATASUCCESS(): TMSG_HEADER(MSG_SENDDATASUCCESS)
        {
        }
    };

#pragma pack()
};

#endif

3 楼

服务器端:


#pragma comment(lib, "WS2_32")

#include <WinSock2.h>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <sstream>
#include <iostream>
#include "comData.h"
using namespace std;
char    g_szDataContent[MAXDATALENGTH]; //客户端传送过来的数据内容
char    g_szBuff[MAX_PACKET_SIZE + 1];
long    g_lLength;
char*    g_pBuff = NULL;
// 初始化socket库
bool InitSocket();
// 关闭socket库
bool CloseSocket();
// 解析消息进行相应的处理
bool ProcessMsg(SOCKET sClient);
// 监听Client的消息
void ListenToClient();
// 解析字符串名字
bool CharaAnalytic(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient);
// 传送数据
bool SendData(SOCKET sClient);


int main()
{
    InitSocket();
    ListenToClient();
    CloseSocket();

    return 0;
}

void ListenToClient()
{
    // 创建socket套接字
    SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (SOCKET_ERROR == sListen)
    {
        printf("Init Socket Error!\n");
        return;
    }

    // 绑定socket到一个本地地址
    sockaddr_in sin;
    sin.sin_family    = AF_INET;
    sin.sin_port    = htons(PORT);
    sin.sin_addr.S_un.S_addr = INADDR_ANY;
    if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
    {
        printf("Bind Error!\n");
        return;
    }

    // 设置socket进入监听状态
    if (::listen(sListen, 10) == SOCKET_ERROR)
    {
        printf("Listen Error!\n");
        return;
    }

    printf("Listening To Client...\n");

    // 循环接收client端的连接请求
    sockaddr_in ClientAddr;
    int nAddrLen = sizeof(sockaddr_in);
    SOCKET sClient;

    while (INVALID_SOCKET == (sClient = ::accept(sListen, (sockaddr*)&ClientAddr, &nAddrLen)))
    {
    }
    cout << "skdjfls" << endl; 
    while (true == ProcessMsg(sClient))
    {
    }

    // 关闭同客户端的连接
    ::closesocket(sClient);

    ::closesocket(sListen);
}

bool InitSocket()
{
    // 初始化socket dll
    WSADATA wsaData;
    WORD socketVersion = MAKEWORD(2, 2);
    if (::WSAStartup(socketVersion, &wsaData) != 0)
    {
        printf("Init socket dll error\n");
        return false;
    }

    return true;
}

4 楼

bool CloseSocket()
{
    // 释放winsock库
    ::WSACleanup();
    if (NULL != g_pBuff)
    {
        delete [] g_pBuff;
        g_pBuff = NULL;
    }
    return true;
}

bool ProcessMsg(SOCKET sClient)
{
    int nRecv = ::recv(sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);
    if (nRecv > 0)
    {
        g_szBuff[nRecv] = '\0';
    }

    // 解析命令
    CCSDef::TMSG_HEADER* pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;
    
    switch (pMsgHeader->cMsgID)
    {
    case MSG_DATA:            // 字符串
        {
            CharaAnalytic(pMsgHeader, sClient);
            return false;
        }
        break;
    case MSG_CLIENT_READY:        // 客户端准备好了,开始传送文件
        {
            SendData(sClient);
            return false;
        }
        break;
    }

    return true;
}

// 解析字符串名字,并传送给客户端所包含的数字
bool CharaAnalytic(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient)
{
    CCSDef::TMSG_DATA* tMsgData = (CCSDef::TMSG_DATA*)pMsgHeader;

    // 对字符串名进行一些处理
    char *p1, *p2;
    for (p1 = tMsgData->dataBuf, p2 = g_szDataContent;'\0' != *p1;++p1, ++p2)
    {
        if ('\n' != *p1)
        {
            *p2 = *p1;
        }
    }
    *p2 = '\0';
    SendData(sClient);
    //CCSDef::TMSG_DATA tmsgData;
    //memcpy(tMsgData->dataBuf, g_szDataContent, MAXDATALENGTH);
    //    ::send(sClient, (char*)(&tMsgData), sizeof(CCSDef::TMSG_DATA), 0);
    cout << "CharaAnalytic..." << endl;
    return true;
}

// 传送数据
bool SendData(SOCKET sClient)
{

    
    int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int);    // 每个数据包存放文件的buffer大小
    // 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送
    //解析字符串
    string str;
    stringstream stream;
    stream << g_szDataContent;
    stream >> str;
    
    cout << "g_szDataContent: " << g_szDataContent << endl;
    string::size_type index = str.find_first_of(",");
    string strfirst = str.substr(0,index);
    string strlast = str.substr(index + 1,string::npos);
    stream.clear();
    int intfirst;
    int intlast;
    stream << strfirst;
    stream >> intfirst;
    stream.clear();
    stream << strlast;
    stream >> intlast;
    cout << "g_szDataContent:111 " << endl << intfirst << endl << intlast <<endl<<"strData:  " << endl << strfirst << endl << strlast << endl << index << endl;

    
    for (int i = intfirst; i < intlast; i += 1)
    {        
        CCSDef::TMSG_SENDDATA tMsgData;
        
        memcpy(tMsgData.tData.szBuff, g_pBuff + tMsgData.tData.nStart, tMsgData.tData.nSize);
        ::send(sClient, (char*)(&tMsgData), sizeof(CCSDef::TMSG_SENDDATA), 0);
        Sleep(0.5);
    }
    return true;
}

5 楼

以下是客户端:

#pragma comment(lib, "WS2_32")

#include <WinSock2.h>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <sstream>
#include "comData.h"
#include <iostream>
using namespace std;
long    g_lLength = 0;
char*    g_pBuff = NULL;
char    g_szFileName[MAXDATALENGTH];
char    g_szBuff[MAX_PACKET_SIZE + 1];
SOCKET    g_sClient;

// 初始化socket库
bool InitSocket();
// 关闭socket库
bool CloseSocket();
// 将<起始数字>,<终止数字> ‘\n’传送到server端
bool SendDataServer();
// 与server端连接
bool ConectToServer();
// 分配缓冲区保存数据
bool AllocateMemoryForData(CCSDef::TMSG_HEADER *pMsgHeader);
// 处理server端传送过来的消息
bool ProcessMsg();

bool CoutNumber(CCSDef::TMSG_HEADER *pMsgHeader);

int main()
{
    InitSocket();
    ConectToServer();

    CloseSocket();

    return 0;
}

// 初始化socket库
bool InitSocket()
{
    // 初始化socket dll
    WSADATA wsaData;
    WORD socketVersion = MAKEWORD(2, 2);
    if (::WSAStartup(socketVersion, &wsaData) != 0)
    {
        printf("Init socket dll error\n");
        exit(-1);
    }

    return true;
}

// 关闭socket库
bool CloseSocket()
{
    // 关闭套接字
    ::closesocket(g_sClient);
    // 释放winsock库
    ::WSACleanup();

    return true;
}

6 楼

// 与server端连接进行数字
bool ConectToServer()
{
    // 初始化socket套接字
    if (SOCKET_ERROR == (g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
    {
        printf("Init Socket Error!\n");
        exit(-1);
    }

    sockaddr_in servAddr;
    servAddr.sin_family = AF_INET;
    servAddr.sin_port    = htons(PORT);
    servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);
    if (INVALID_SOCKET == (::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in))))
    {
        printf("Connect to Server Error!\n");
        exit(-1);
    }

    // 将<起始数字>,<终止数字> ‘\n’传送到server端
    SendDataServer();

    // 接收server端传过来的信息,并打印到控制台
    while (true == ProcessMsg())
    {
    }

    return true;
}

// 将<起始数字>,<终止数字> ‘\n’传送到server端
bool SendDataServer()
{
    printf("Input Data : ");
    string strData;
    cin >> strData;
    char sendData[100];
    stringstream  stream;
    stream << strData;
    stream >> sendData;
    //将超始数字,终止数字 发送到Server端
    
    // 把文件路径发到server端
    CCSDef::TMSG_DATA* pRequestFilenameMsg = (CCSDef::TMSG_DATA*)pMsgHeader;
    CCSDef::TMSG_DATA tMsgRequestFileName;
    strcpy(tMsgRequestFileName.dataBuf, sendData);
    if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_DATA), 0))
    {
        printf("Send Content Error!\n");
        exit(-1);
    }
    cout << "send sendData to server:" << sendData << endl;
    return true;
}

// 处理server端传送过来的消息
bool ProcessMsg()
{
    CCSDef::TMSG_HEADER *pMsgHeader;
    int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);
    
    pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;

    switch (pMsgHeader->cMsgID)
    {
    case MSG_DATA:                //
        {
            cout << "allocate memory for data: " << endl;
            return AllocateMemoryForData(pMsgHeader);
        }
        break;
    case MSG_SENDDATA:
        {
            CoutNumber(pMsgHeader);
        }
    }
    //cout << "client msg:" << pMsgHeader->cMsgID << endl;
    return true;
}



// 分配缓冲区保存数据
bool AllocateMemoryForData(CCSDef::TMSG_HEADER *pMsgHeader)
{
    assert(NULL != pMsgHeader);

    if (NULL != g_pBuff)
    {
        return true;
    }

    // 分配缓冲区开始接收数据,如果分配成功就给server端发送开始传送数据的要求
    g_pBuff = new char[g_lLength + 1];
    if (NULL != g_pBuff)
    {
        memset(g_pBuff, '\0', g_lLength + 1);
        CCSDef::TMSG_DATA* pRequestFilenameMsg = (CCSDef::TMSG_DATA*)pMsgHeader;
        printf("Now ready to get the data %s!\n", pRequestFilenameMsg->dataBuf);
        CCSDef::TMSG_CLIENT_READY tMsgClientReady;

        if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0))
        {
            printf("Send Error!\n");
            exit(-1);
        }
    }
    else
    {
        printf("Alloc memory for data error!\n");
        exit(-1);
    }
    CCSDef::TMSG_CLIENT_READY tMsgClientReady;
    if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0))
    {
        printf("Send Error!\n");
        exit(-1);
    }
    return true;
}

//输出内容
bool CoutNumber(CCSDef::TMSG_HEADER *pMsgHeader)
{
    assert(NULL != pMsgHeader);

    CCSDef::TMSG_SENDDATA* pMsgData = (CCSDef::TMSG_SENDDATA*)pMsgHeader;
    char buf[50];
    memcpy(buf, pMsgData->dataBuf, MAXDATALENGTH);
    cout << buf << endl;
    return true;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册