客户端:/*****************************************************************
 *
 * Description:
 * TCP协议传输测试,客户端
 *
 * Usage:
 * sender [-p:int] [-r:IP] [-n:x] [-b:x] [-t:x]
 * -p:int   服务器监听端口
 * -r:IP    服务器IP
 * -n:x     发送包的次数
 * -b:x     发送包的大小
 * -t:x     发送间隔
 * c1-2011.9.8
 *****************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "wsock32.lib")
#include <process.h>
#include <windows.h> #define DEFAULT_PORT            8000  //默认端口号
#define DEFAULT_COUNT           5  //默认发送次数
#define DEFAULT_CHAR            'a'      //默认填充字符
#define DEFAULT_BUFFER_LENGTH   8192     //默认包大小是8K
#define DEFAULT_INTERVAL        1000     //默认间隔时间是1秒
#define DEFAULT_PER_COUNT       1        //默认每一次发送的包个个数
BOOL  bConnect = FALSE;                 // 先连接服务器标志
int   iPort    = DEFAULT_PORT;
int   itime    = DEFAULT_INTERVAL;
char  cChar    = DEFAULT_CHAR;
int   dwCount  = DEFAULT_COUNT;
int   dwLength = DEFAULT_BUFFER_LENGTH;
int   dwPcount = DEFAULT_PER_COUNT;
const char *keepalive="HELLO";
char   *recvbuf=NULL;
char  szRecipient[128];                 // 服务器地址
int lock=0; /*互斥锁*//*********************************************
 * Function: usage
 * Description:
 * 打印帮助信息并退出
 ********************************************/
void tip(char *name)
{
    printf("usage: %s [-p:int] [-r:IP] [-n:x] [-b:x] [-d:c] [-m:x]\n\n", name);
    printf("       -p:int   服务器监听端口, 缺省为%d\n", DEFAULT_PORT);    
    printf("       -r:IP    服务器IP\n");
printf("       -n:x     发送数据次数, 缺省为%d次\n", DEFAULT_COUNT);
    printf("       -b:x     发送包的大小,缺省为%d字节\n",DEFAULT_BUFFER_LENGTH);
    printf("       -t:x     发送间隔时间,缺省为%d秒\n",DEFAULT_INTERVAL);
    printf("       -m:x     每次发送包的个数,缺省值为%d个\n",DEFAULT_PER_COUNT);
    ExitProcess(1);
}/*********************************************
 * Function: ValidateArgs
 * Description:
 * 命令行解析 
 ********************************************/void ValidateArgs(int argc, char **argv)
{
int i;
if (argc < 2)
tip(argv[0]);
for (i = 1; i < argc; i++) 
{
if (strlen(argv[i]) <= 3 || strchr("-/", *argv[i]) == NULL)
{
continue;

switch (tolower(argv[i][1])) 
{
case 'p':
                   if (strlen(argv[i]) > 3)
                        iPort = atoi(&argv[i][3]);
                    break;

                case 'r':
                    if (strlen(argv[i]) > 3)
                        strcpy(szRecipient, &argv[i][3]);
                    break; case 'n':
if (strlen(argv[i]) > 3)
dwCount = atol(&argv[i][3]);
break; case 'b': if (strlen(argv[i]) > 3)
dwLength = atol(&argv[i][3]);
break;
case 't':
if (strlen(argv[i]) > 3)
itime = atol(&argv[i][3]);
break;
case 'm':
if(strlen(argv[i])>3)
dwPcount=atol(&argv[i][3]);
break;
default:
tip(argv[0]);
break;
}
}
}//依照指定次数和发送间隔发送数据包
void keep_alive(SOCKET * pragma)
{
SOCKET clisocket= (SOCKET)pragma;
int i;
int ret;
for (i = 0; i<dwCount; i++)
{
while(lock==1)
{
Sleep(itime);
}
lock = 1;
ret = send(clisocket,"hello", strlen("hello")+1, 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed: %d\n", WSAGetLastError());
lock =0;
break;
}
else if ( ret == 0)
{
lock = 0; 
break;
}
else
{
Sleep(1000);
ret=recv(clisocket, recvbuf, sizeof(recvbuf), 0);
printf("%d\n",ret);
printf("%s\n",recvbuf);
memset(recvbuf, 0, (dwLength-1));
lock =0;
}
Sleep(itime); } /*closesocket(clisocket);
GlobalFree(recvbuf);
WSACleanup();*/}
int main(int argc, char **argv)
{
WSADATA    wsd;
SOCKET    s;
char    *sendbuf=NULL;
int    ret;
int        i,j;
char   *recvbuf=NULL; SOCKADDR_IN serverIP; ValidateArgs(argc, argv); if (WSAStartup(MAKEWORD(2, 2), &wsd) !=NO_ERROR) 
{
printf("WSAStartup() failed!\n");
return 1;
} //TCP客户端启动
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
printf("socket() failed: %d\n", WSAGetLastError());
return 1;
} // 服务器地址设置
serverIP.sin_family = AF_INET;
serverIP.sin_port = htons((short)iPort);
serverIP.sin_addr.s_addr = inet_addr(szRecipient); 
if (serverIP.sin_addr.s_addr== INADDR_NONE) 
{
struct hostent *host = NULL; host = gethostbyname(szRecipient);
if (host)
CopyMemory(&serverIP.sin_addr, host->h_addr_list[0],
host->h_length);
else
{
printf("gethostbyname() failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
} printf("服务器监听端口:%d\t发送包的次数: %d\n",iPort, dwCount);
printf("发送包的大小:%d\t包的时间间隔:%d\n",dwLength, itime);
printf("每次发送包的个数:%d\n",dwPcount);

//设置发送缓冲区
    sendbuf =(char *) GlobalAlloc(GMEM_FIXED, dwLength);
recvbuf =(char *) GlobalAlloc(GMEM_FIXED, dwLength);
    if (!sendbuf) 
{
        printf("GlobalAlloc() failed: %d\n", GetLastError());
        return 1;
    }
    sendbuf[dwLength-1] = '\0';
    memset(sendbuf, cChar, (dwLength-1));
memset(recvbuf, 0, (dwLength-1));
s = socket(AF_INET, SOCK_STREAM, 0);
//连接服务器
 if (connect(s, (SOCKADDR *)&serverIP, sizeof(serverIP)) ==SOCKET_ERROR) 
{
printf("connect() failed: %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}
 _beginthread((void (__cdecl *) (void *))keep_alive,0,(SOCKET *)s);

/* for (i = 0; i<dwCount; i++)
{
ret = send(clisocket, sendbuf, dwLength, 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed: %d\n", WSAGetLastError());
break;
}
else if ( ret == 0)
{
break;
}
else
{
Sleep(1000);
ret=recv(clisocket, recvbuf, sizeof(recvbuf), 0);
printf("%d\n",ret);
printf("%s\n",recvbuf);
memset(recvbuf, 0, (dwLength-1));
}
Sleep(itime);
} closesocket(s);
GlobalFree(sendbuf);
WSACleanup();*/
while (1) 
{
printf("if you want to send messeage ,please input your message :");
 gets(sendbuf);
 while(lock==1)
 {
Sleep(itime);
 }
 lock=1;
 ret = send(s, sendbuf, dwLength, 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed: %d\n", WSAGetLastError());
lock=0;
break;
}
else if ( ret == 0)
{
lock=0;
break;
}
else
{
Sleep(1000);
ret=recv(s, recvbuf, sizeof(recvbuf), 0);
printf("%d\n",ret);
printf("%s\n",recvbuf);
memset(recvbuf, 0, (dwLength-1));
lock=0;
}
}
WaitForSingleObject(keep_alive,INFINITE);
closesocket(s);
WSACleanup();
return 0;}线程为什么发不出去数据?非常不能理解,但是如果在主函数中直接发送是能够成功的!线程是想实现一个保活保文,我上面的程序中只是循环里几次,其实应该是一个无限循环的。

解决方案 »

  1.   

    服务器端:
    #include <winsock2.h> 
    #include <stdio.h> 
    #pragma comment(lib, "ws2_32.lib") 
    int main() 

        // 加载win socket 
        WSADATA ws; 
     DWORD err;
        int ret; 
    // 创建套接字集合 
        fd_set allSockSet; // 总的套接字集合 
        fd_set readSet; // 可读套接字集合 
        fd_set writeSet; // 可写套接字集合
    SOCKET sListen; 
    SOCKET sClient;
    SOCKADDR_IN servAddr; 
    SOCKADDR_IN clientAddr; 
      unsigned int i;
      unsigned int j;
      int len;
        
        char bufRecv[100]; 
    char recvbuf[10240];// 接收缓冲区
    char sendbuf[10240];  
        ret = WSAStartup(MAKEWORD(2, 2), &ws); 
        if (ret != 0) 
        { 
            printf("WSAStartup() 失败!\n"); 
            return -1; 
        } 
         // 创建侦听SOCKET 
        sListen = socket(AF_INET, SOCK_STREAM, 0); 
        if (sListen == INVALID_SOCKET) 
        { 
            printf("socket() 失败!\n"); 
            return -1; 
        } 
        // 填充服务器地址结构     servAddr.sin_family = AF_INET; 
        servAddr.sin_addr.s_addr = INADDR_ANY; 
        servAddr.sin_port = htons(8000);    // 绑定服务器套接字 
        ret = bind(sListen, (SOCKADDR*)&servAddr, sizeof(servAddr)); 
        if (ret == SOCKET_ERROR) 
        { 
            printf("bind() 失败!\n"); 
            return -1; 
        }    // 开始侦听 
        ret = listen(sListen, 5); 
        if (ret == SOCKET_ERROR) 
        { 
            printf("listen() 失败!\n"); 
            return -1; 
        } 
        printf("服务器启动成功,在端口%d监听…\n", ntohs(servAddr.sin_port)); 
        //使用select模型 
       
        // 进入服务器主循环 
    FD_ZERO(&allSockSet); // 清空套接字集合 
        FD_SET(sListen, &allSockSet); // 将sListen套接字加入套接字集合中 
        while(1) 

            FD_ZERO(&readSet); // 清空可读套接字 
            FD_ZERO(&writeSet); // 清空可写套接字 
            readSet = allSockSet; // 赋值 
            writeSet = allSockSet; // 赋值 
    // 调用select函数,timeout设置为NULL 
            ret = select(0, &readSet, 0, NULL, NULL); 
            // 
            if (ret == SOCKET_ERROR) 
            { 
                printf("select() 失败!\n"); 
                return -1; 
            } 
            // 存在套接字的I/O已经准备好 
            if(ret > 0) 
            { 
                // 遍历所有套接字 
                for (i=0;i<allSockSet.fd_count;++i) 
                { 
                    SOCKET s = allSockSet.fd_array[i]; 
                    // 存在可读的套接字 
                    if (FD_ISSET(s, &readSet)) 
                    { 
                        // 可读套接字为sListen 
                        if (s == sListen) 
                        { 
                            // 接收新的连接 
                          
                            len= sizeof(clientAddr); 
                            sClient = accept(s, (SOCKADDR*)&clientAddr, &len); 
                            // 将新创建的套接字加入到集合中 
                            FD_SET(sClient, &allSockSet); 
                            printf(">>>>>有新的连接到来啦…\n"); 
                            printf("目前客户端数目为:%d\n", allSockSet.fd_count - 1); 
    ret=recv(sClient, recvbuf, sizeof(recvbuf)+1, 0);
    printf("from %u ,%d bytes!\n",ntohs(clientAddr.sin_port),ret);
    ret=send(sClient, "ack", strlen("ack")+1, 0);
                        } 
                        else // 接收客户端信息 
                        { 
                            ret = recv(s, bufRecv, 100, 0); 
                            // 接收错误 
                            if (ret == SOCKET_ERROR) 
                            { 
                                err= WSAGetLastError(); 
                                if (err == WSAECONNRESET) 
                                printf("客户端被强行关闭\n"); 
                                else 
                                printf("recv() 失败!"); 
                                // 删除套接字 
                                FD_CLR(s, &allSockSet); 
                                printf("目前客户端数目为:%d\n", allSockSet.fd_count - 1); 
                                break; 
                            } 
                            if (ret == 0) 
                            { 
                                printf("客户端已经退出!\n"); 
                                // 删除套接字 
                                FD_CLR(s, &allSockSet); 
                                printf("目前客户端数目为:%d\n", allSockSet.fd_count - 1); 
                                break; 
                            } 
                            bufRecv[ret] = '\0'; 
    if(strcmp(bufRecv,"hello"))
    {
    ret=send(s, "ack", strlen("ack")+1, 0);
    printf("%d",ret);
    }
    else
    {
    sClient = accept(s, (SOCKADDR*)&clientAddr, &len);
    /* sprintf(sendbuf,"IP地址为:%s ,端口号为:%u,长度为:%d bytes!\n 
    消息为:%s\n",
    inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port),ret
    bufRecv);*/
    printf("IP地址为:%s ,端口号为:%u,长度为:%d bytes!\n",inet_ntoa(clientAddr.sin_addr),
    ntohs(clientAddr.sin_port),ret);
    printf("消息为:%s\n", bufRecv);
    for (j=0;j<allSockSet.fd_count;++j) 

    if(allSockSet.fd_array[i]!=sClient)
    {
    ret=send(sClient,sendbuf,sizeof(sendbuf),0);
    printf("%d",ret);
    }


    }

                        } // end else                }// end if            }// end for 
            } // end if 
        }//end while 
        return 0; 
    }
      

  2.   

    楼主,这是VB版,不是C,你可以把这个问题放到C版去。