tcp udp
区别
-
tcp是面向连接的,udp无连接的协议
-
tcp是可靠的有序的
-
udp是高速的
-
首部大小不同,udp8个字节,tcp20个字节
-
udp没有拥塞控制
-
tcp:流模式,udp:数据包模式
-
应用:udp:游戏下载
udp
client
#include "stdafx.h"
#include "Winsock2.h"
#include "stdio.h"
#include "windows.h"
//没有下面这句,所有的通讯函数都将报错
#pragma comment(lib,"ws2_32.lib")//必须链接这个库
#define recvAddr "10.185.32.235"
//发送端程序
void main()
{ //初始化socket库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
// 下面的函数是连接应用程序与winsock.dll的第一个调用.
// 第一个参数是WINSOCK 版本号,第二个参数是指向WSADATA的指针.
// 该函数返回一个INT型值,通过检查这个值来确定初始化是否成功
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("WSAStartup错误!!!!");
system("pause");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{ WSACleanup( );
return;
}
SOCKET sockClient = socket( AF_INET , SOCK_DGRAM , 0 ) ;//建立socket,设置采用UDP方式通信
SOCKADDR_IN addrSrv ; //本机接收信息时,对方的IP地址,不设置时所有IP地址发送过来的信息都会被接收到
addrSrv.sin_addr.S_un.S_addr =inet_addr(recvAddr) ;//远程主机的IP地址,127是本机的回送地址,实际没有任何网络传输
addrSrv.sin_family = AF_INET ;
addrSrv.sin_port = htons(1234) ;//远程主机的端口port
char sendBuf[10]="" ;
char recvBuf[50]="" ;
char tempBuf[50]="" ;
int len = sizeof(SOCKADDR) ;
int a=100,b=0,c=0;
char a1[3],b1[3]c1[3];
while (1)
{
itoa(a,a1,10);
itoa(b,b1,10);
itoa(c,c1,10);
_snprintf(sendBuf,9, "%3s%3s%3s",a1,b1,c1 );//将a1,b1,c1按第三个形参的格式生成一个char型数组,并将第三个形参char数组中的前9个元素写入senBuf数组的前九个位置
sendBuf[9]='0';
sendto( sockClient , sendBuf , 10 , 0 , (SOCKADDR*)&addrSrv , len ) ;//发送10个char数组
for(int i =0;i<50;i++)
{
tempBuf[i]=' ';
}
printf( "send\n" ) ;
if(b<100)
{
b+=1;
if(a>20)
b=a-15;
else if(b>10)
c=b-10;
else if(tested>5)
c=b-5;
}
else
{
a=100,b=0,c=0;
}
Sleep(1000);
}
closesocket(sockClient) ;//关闭socket
WSACleanup() ;
}
server
#include "stdafx.h"
#include "Winsock2.h"
#include "stdio.h"
#include "windows.h"
#pragma comment(lib,"ws2_32.lib") //没有下面这句,所有的通讯函数都将报错
void main()
{ //初始化socket库
WORD wVersionRequested;
WSADATA wsaData; //wsaData用来存储系统传回的关于WINSOCK的资料
int err;
wVersionRequested = MAKEWORD( 1, 1 );
// 下面的函数是连接应用程序与winsock.dll的第一个调用.
// 第一个参数是WINSOCK 版本号,第二个参数是指向WSADATA的指针.
// 该函数返回一个INT型值,通过检查这个值来确定初始化是否成功
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) return;
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{ WSACleanup( );
return;
}
SOCKET sockSrv = socket( AF_INET , SOCK_DGRAM , 0 ) ;
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr =inet_addr("10.185.32.235");
addrSrv.sin_family = AF_INET ,
addrSrv.sin_port = htons(1000) ;
bind( sockSrv , (SOCKADDR*)&addrSrv , sizeof(SOCKADDR) ) ;//将SOCKET和指定的IP地址端口绑定在一起,本SOCKET就用第二个形参设定好的IP端口和其他主机进行通信
char sendBuf[100]="received" ;
char recvBuf[100]="" ;
char tempBuf[200]="" ;
SOCKADDR_IN addrClient ;//这里没有设置IP地址,所以所有的IP发的UDP信息都会被本机接收到
int len = sizeof(SOCKADDR) ;
while (1)
{
recvfrom(sockSrv,recvBuf,9,0,(SOCKADDR*)&addrClient,&len) ;//接收9个char型字符并赋值给recvBuf数组的前九个元素
_snprintf(tempBuf,24,"%s say: %s\n",inet_ntoa(addrClient.sin_addr),recvBuf) ;
for(int i =0;i<50;i++)
{
tempBuf[i]=' ';
recvBuf[i]=' ';
}
sendto(sockSrv,sendBuf,9,0,(SOCKADDR*)&addrClient,len) ;
}
closesocket( sockSrv ) ;
WSACleanup() ;
}
tcp
client:
#include "pch.h"
#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(1234);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "服务器连接失败!" << endl;
WSACleanup();
}
else {
cout << "服务器连接成功!" << endl;
}
//发送,接收数据
while (1) {
cout << "请输入发送信息:";
cin >> send_buf;
send_len = send(s_server, send_buf, 100, 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
recv_len = recv(s_server, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
else {
cout << "服务端信息:" << recv_buf << endl;
}
}
//关闭套接字
closesocket(s_server);
//释放DLL资源
WSACleanup();
return 0;
}
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
server:
#include "pch.h"
#include<iostream>
#include<winsock.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
int len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
SOCKET s_accept;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
SOCKADDR_IN accept_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(5010);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "套接字绑定失败!" << endl;
WSACleanup();
}
else {
cout << "套接字绑定成功!" << endl;
}
//设置套接字为监听状态
if (listen(s_server, SOMAXCONN) < 0) {
cout << "设置监听状态失败!" << endl;
WSACleanup();
}
else {
cout << "设置监听状态成功!" << endl;
}
cout << "服务端正在监听连接,请稍候...." << endl;
//接受连接请求
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR *)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
cout << "连接失败!" << endl;
WSACleanup();
return 0;
}
cout << "连接建立,准备接受数据" << endl;
//接收数据
while (1) {
recv_len = recv(s_accept, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
else {
cout << "客户端信息:" << recv_buf << endl;
}
cout << "请输入回复信息:";
cin >> send_buf;
send_len = send(s_accept, send_buf, 100, 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
//关闭套接字
closesocket(s_server);
closesocket(s_accept);
//释放DLL资源
WSACleanup();
return 0;
}
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
代码过程以及区别:
(1)创建套接字时,第二个参数不同
(2)tcp客户端多了一个connect的过程
(3) udp发送接受是sendto ,recvfrom tcp是 send,recv
因为sendto加了目标的地址,和端口
tcp绑定后就可以不用