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 , 网络编程