TCP (
Transmission Control Protocol)
传输控制协议
通过三次握手
建立连接,通讯完成时要拆除连接,比较可靠
服务端
sListen
=socket(
AF_INET, /*用来指定套接字使用的地址格式,winsock中只支持AF_INET*/
SOCK_STREAM, /*用来指定套接字类型。
SOCK_STREAM 流套接字:TCP,
SOCK_DGRAM 数据报套接字:UDP,
SOCK_RAW 原始套接字,*/
0/*配合上一个参数使用,用来指定使用的协议类型。
常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议
*/
);
//构建本地地址信息
saServer
//绑定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("bind() faild! code:%d\n", WSAGetLastError());
closesocket(sListen); //关闭套接字
WSACleanup();
//return 0;
}
//侦听连接请求
ret = listen(sListen, 5);
if (ret == SOCKET_ERROR)
{
...
}
//阻塞等待接受客户端连接
while(1)
{
length = sizeof(saClient);
sServer = accept(sListen, (struct sockaddr *)&saClient, &length);
参数sockfd:套接口描述字,该套接口在listen()后监听连接。addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。
if (sServer == INVALID_SOCKET)
{
....
}
char sendMessage[]="hello client"; //发送信息给客户端
send(sServer,sendMessage,strlen(sendMessage)+1,0);
char receiveMessage[5000];
nLeft = sizeof(receiveMessage);
ptr = (char *)&receiveMessage;
while(nLeft>0)
{
//接收数据
ret = recv(sServer, ptr, 5000, 0);
sockfd: 接收端套接字描述符
buff: 用来存放recv函数接收到的数据的缓冲区nbytes: 指明buff的长度flags: 一般置为01) 如果套接字sockfd的发送缓冲区中没有数据或者数据被协议成功发送完毕后,recv先检查套接字sockfd的接收缓冲区,如果sockfd的接收缓冲区中没有数据或者协议正在接收数据,那么recv就一起等待,直到把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲区中的数据copy到buff中(注意协议接收到的数据可能大于buff的长度,所以在这种情况下要调用几次recv函数才能把sockfd的接收缓冲区中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的)2) recv函数返回其实际copy的字节数,如果recv在copy时出错,那么它返回SOCKET_ERROR。如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
if (ret == SOCKET_ERROR)
{
printf("recv() failed!\n");
return 0;
}
if (ret == 0) //客户端已经关闭连接
{
printf("Client has closed the connection\n");
break;
}
nLeft -= ret;
ptr += ret;
}
printf("receive message:%s\n", receiveMessage);//打印我们接收到的消息。
}
客户端
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
WSACleanup();
printf("socket() failed!\n");
//return 0;
}
//构建服务器地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意转化为网络节序
saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//连接服务器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf("connect() failed!\n");
closesocket(sClient); //关闭套接字
WSACleanup();
//return 0;
}
char sendMessage[]="ZhongXingPengYue";
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
if (ret == SOCKET_ERROR)
{
printf("send() failed!\n");
}
else
printf("client info has been sent!");
char recvBuf[100];
recv(sClient,recvBuf,100,0);
printf("%s\n",recvBuf);
closesocket(sClient); //关闭套接字
WSACleanup();
getchar();