当前位置:编程学习 > VB >>

C语言编程模拟TCP通信程序,为什么总是出错。





客户端:

/*****************************************************************
 *
 * 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;

}

线程为什么发不出去数据?非常不能理解,但是如果在主函数中直接发送是能够成功的!线程是想实现一个保活保文,我上面的程序中只是循环里几次,其实应该是一个无限循环的。 --------------------编程问答-------------------- 服务器端:
#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; 
}
--------------------编程问答-------------------- 楼主,这是VB版,不是C,你可以把这个问题放到C版去。
补充:VB ,  网络编程
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,