socket高手请进来指点一下
写了一个用socket收发数据(send,recv)的console程序,客户端发送,服务器端收数据并回显,最大线程数是十个(每个客户端一个),现把服务器端代码贴出来,望高手指点一下:
#include "stdafx.h"
#define NUMBER 10
SOCKET NewSocket[NUMBER];
//线程处理段,解决多连接的数据处理问题
void ProceData(PVOID ii)
{
char DataBuffer[1024];
memset(DataBuffer,0,sizeof(DataBuffer));
int i = *((int *)ii);
int Ret;
while(1)
{
if ((Ret = recv(NewSocket[i],DataBuffer,sizeof(DataBuffer),0))!= SOCKET_ERROR)
{
if (Ret > 0)
{
//printf("We Have received %d bytes from the client\n",Ret);
printf("收到的数据是: %s\n",DataBuffer);
}
}
Sleep(1);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
SOCKET LisenSocket;
SOCKADDR_IN Serveraddr,Clientaddr;
int Ret,ClientaddrLen;
char DataBuffer[1024];
int port = 5500;
BOOL sc = TRUE;
HANDLE hThd[NUMBER];
int nThd;
//初始化winsock 版本库
if ((Ret = WSAStartup(MAKEWORD(2,2),&wsaData)) != 0)
{
printf("WSAStartup failed with error code %d \n", Ret);
return -1;
}
//创建socket套结字
if ((LisenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Create the socket failed with error code %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
Serveraddr.sin_family = AF_INET;
Serveraddr.sin_port = htons(port); //将端口地址转换为网络字节
Serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); //将ip地址转换为网络字节
if ((Ret = bind(LisenSocket,(SOCKADDR *)&Serveraddr,sizeof(Serveraddr))) == SOCKET_ERROR)
{
printf("bind the socket failed with error code %d\n",WSAGetLastError());
closesocket(LisenSocket);
WSACleanup();
return -1;
}
//监听客户机连接,确定最大连接数
listen(LisenSocket,NUMBER);
//接受一个新的连接
printf("We are waiting a connection on port %d.\n", port);
int i = 0;
int j;
ClientaddrLen = sizeof(Clientaddr);
while(i < NUMBER)
{
if ((NewSocket[i] = accept(LisenSocket, (SOCKADDR *)&Clientaddr,&ClientaddrLen)) == INVALID_SOCKET)
{
Ret = WSAGetLastError();
printf("We have tryed to accept a socket for the %d times...\n", ++i);
switch(Ret)
{
case WSANOTINITIALISED:
printf("A successful WSAStartup call must occur before using this function.\n");
break;
case WSAENETDOWN:
printf("The network subsystem has failed.\n");
break;
case WSAEFAULT:
printf("The addrlen parameter is too small or addr is not a valid part of the user address space\n");
break;
case WSAEINTR:
printf("A blocking Windows Sockets 1.1 call was canceled through WSACancelBlockingCall.\n");
break;
case WSAEINPROGRESS:
printf("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.\n");
break;
case WSAEINVAL:
printf("The listen function was not invoked prior to accept.\n");
break;
case WSAEMFILE:
printf("The queue is nonempty upon entry to accept and there are no descriptors available\n");
break;
case WSAENOBUFS:
printf("No buffer space is available.\n");
break;
case WSAENOTSOCK:
printf("The descriptor is not a socket\n");
break;
case WSAEOPNOTSUPP:
printf("The referenced socket is not a type that supports connection-oriented service.\n");
break;
case WSAEWOULDBLOCK:
printf("The socket is marked as nonblocking and no connections are present to be accepted\n");
break;
default:
printf("a unknown error eccured\n");
break;
}
//Sleep(100);
}
else
{
//inet_ntoa()函数将ipv4 internet地址转换为char far *
j = i;
printf("We successfully got a connection from %s:%d.\n",inet_ntoa(Clientaddr.sin_addr), ntohs(Clientaddr.sin_port));
hThd[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&ProceData,(LPVOID)&j,0,(PULONG)&nThd);
i++;
}
}
Ret = GetTickCount();
Sleep(90000000000000);
//释放空间
for (int k = 0; k < i; k++)
{
if (hThd[k] != NULL)
CloseHandle(hThd[k]);
if (NewSocket[k] != INVALID_SOCKET)
closesocket(NewSocket[k]);
}
Ret = GetTickCount() - Ret;
printf("The thread has been in %d seconds\n",Ret);
printf("over\n");
//关闭winsock
WSACleanup();
return 0;
}
先提出问题如下:
一:本来想在createthread()时,将第三个参数直接赋值为NewSocket[i],但是总提示参数不匹配,只好将其下标传过去,并将NewSocket[i]定义成了全局变量,不知道该如何解决??
二:在发送端如果发送的字符中包含空格,则空格后面的字符都收不到??
三:如果启十个客户端并频繁的发送数据,会出现丢包,即收到的数据为空??
四:主线程不知道该如何控制子线程,感知它的存在与否?
五:若客户端close一个,服务器怎么知道,并释放相应的空间?
六:第一次写这方面的东西,处理方法上一定有很多不合理的地方,望指点一下。
呵呵,提的问题太多了,若哪位高手有完美的代码,不吝赐教吧。多谢了!!