TCPIPTCP群聊的实现文档格式.docx
《TCPIPTCP群聊的实现文档格式.docx》由会员分享,可在线阅读,更多相关《TCPIPTCP群聊的实现文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
stdio.h>
string.h>
iostream>
//服务器端口号为5050
#defineDEFAULT_PORT5050
//接收数据缓冲区长度
#defineBUFFER_LENGTH1024
#pragmacomment(lib,"
ws2_32.lib"
)
usingnamespacestd;
voidmain()
{
intiPort=DEFAULT_PORT;
WSADATAwsaData;
SOCKETsSocket;
//客户地址长度
intiLen;
//发送的数据长度
intiSend;
//接受的数据长度
intiRecv;
//要发送给客户的信息
charsend_buf[BUFFER_LENGTH];
//接收数据的缓冲区
charrecv_buf[BUFFER_LENGTH];
//本地地址和客户地址
structsockaddr_inser,cli;
structsockaddr_intemp;
//structsockaddr_inclis[100];
char**clis;
printf("
----------------------\n"
);
SercerWaiting\n"
if(WSAStartup(MAKEWORD(2,2),&
wsaData)!
=0)
{
printf("
FailedtoloadWinsock.\n"
return;
}
//产生服务器端套接口
sSocket=socket(AF_INET,SOCK_DGRAM,0);
if(sSocket==INVALID_SOCKET)
socket()Failed:
%d\n"
WSAGetLastError());
ser.sin_family=AF_INET;
ser.sin_port=htons(iPort);
ser.sin_addr.s_addr=htonl(INADDR_ANY);
temp.sin_family=AF_INET;
temp.sin_port=htons(iPort);
if(bind(sSocket,(LPSOCKADDR)&
ser,sizeof(ser))==SOCKET_ERROR)
bind()Failed:
iLen=sizeof(cli);
inti=0;
int*flag;
clis=newchar*[100];
flag=newint[100];
chars2[]="
quit"
;
while
(1)
memset(recv_buf,0,sizeof(recv_buf));
iRecv=recvfrom(sSocket,recv_buf,BUFFER_LENGTH,0,(SOCKADDR*)&
cli,&
iLen);
if(i<
1)
{
clis[i]=newchar[strlen(inet_ntoa(cli.sin_addr))];
strcpy(clis[i],inet_ntoa(cli.sin_addr));
flag[i]=1;
if(iRecv==SOCKET_ERROR)
{
printf("
recvfrom()Failed:
break;
}
else
if(iRecv==0)
break;
else
{
printf("
AcceptedclientIP:
[%s],port:
[%d]\n"
inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
%s\n"
recv_buf);
stringrecv=recv_buf;
stringstr1=recv.substr(8);
constchar*s1=str1.c_str();
if(strcmp(s1,s2)==0)
flag[i]=0;
else
{
temp.sin_addr.s_addr=inet_addr(clis[i]);
iSend=sendto(sSocket,recv_buf,strlen(recv_buf),0,(SOCKADDR*)&
temp,sizeof(temp));
if(iSend==SOCKET_ERROR)
{
printf("
sendto()Failed:
---------------------------\n"
break;
}
else
if(iSend==0)
break;
else
{
printf("
sendto()succeeded:
printf("
}
}
}
i++;
continue;
}
else
for(intk=0;
k<
i;
k++)
if(strcmp(clis[k],inet_ntoa(cli.sin_addr))==0)
flag[k]=0;
if(k<
i-1)
continue;
clis[i]=newchar[strlen(inet_ntoa(cli.sin_addr))];
strcpy(clis[i],inet_ntoa(cli.sin_addr));
stringrecv=recv_buf;
if(strcmp(s1,s2)==0)
flag[i]=0;
flag[i]=1;
i++;
//printf("
yicunIP:
[%s]:
"
clis[i]);
else
for(intj=0;
j<
i;
j++)
if(flag[j]==1)
temp.sin_addr.s_addr=inet_addr(clis[j]);
iSend=sendto(sSocket,recv_buf,strlen(recv_buf),0,(SOCKADDR*)&
if(iSend==SOCKET_ERROR)
if(iSend==0)
break;
else
{
printf("
}
该用户已退出!
\n"
closesocket(sSocket);
WSACleanup();
}
2.Client_Receive部分:
voidmain(intargc,char*argv[])
structsockaddr_inser;
******************************\n"
******WaitingReceive...******\n"
iLen=sizeof(ser);
ser,&
if(iRecv==SOCKET_ERROR)
printf("
break;
if(iRecv==0)
else
3.Client_Send部分:
string>
SOCKETsClient;
//退出
char*quit="
charsend_buf[1024],send_name[]="
段广花:
//服务器地址
if(argc<
2)
Usage:
client[serverIPaddress]\n"
ser.sin_family=AF_INET;
ser.sin_port=htons(iPort);
ser.sin_addr.s_addr=inet_addr(argv[1]);
sClient=socket(AF_INET,SOCK_DGRAM,0);
if(sClient==INVALID_SOCKET)
memset(send_buf,0,sizeof(send_buf));
cout<
<
send_name;
cin>
>
send_buf;
iLen=sizeof(ser);
stringsend_b=send_buf;
stringsend_n=send_name;
stringsend0=send_n+send_b;
constchar*send=send0.c_str();
Sleep(500);
iSend=sendto(sClient,send,strlen(send),0,(structsockaddr*)&
ser,iLen);
//退出
if(strcmp(send_buf,quit)==0)
本机已退出!
closesocket(sClient);
return;
closesocket(sClient);
五、实验结果:
首先服务器端必须启动,如果不成功的话客户端发送的消息就无响应,服务器端只能启动一个进程,不能启动多个服务器,可以启动多个客户端进行通信,支持字符类型输入(包括汉字)。
经测试可得客户端可以通过服务器实现群聊的功能,实验完成。
Server:
段广花Send:
段广花Receive:
冯小龙Send:
冯小龙Receive:
杨凯军Send:
杨凯军Receive:
六、实验反思
此次试验做的很纠结,非常纠结,开始的时候我们想用sockaddr_in的结构体数组来存储每个客户端的IP信息,但是在经过多次尝试后放弃了这个想法,改用char**数组来存储客户端的IP。
在测试期间,还有信息多次发送的问题,经过排查,是同一IP多次存储造成的,经过了好一段时间,才把那段存储Ip地址的代码的逻辑顺序修改正确。
总的来说,这次收获真的是很大的。