使用Socket 创建 TCP、UDP 通信(Windows)

Socket的使用可以分为TCP方式、UDP方式,下面就对两种使用方式进行简单的总结

1、TCP方式

TCP方式即点对点的方式,需要建立连接之后才能进行Socket通信。

服务器端:

在建立服务器端的Socket时,服务其端需要进行:

1、初始化SOCKET运行库;

2、配置通信地址;

3、创建(socket)SOCKET;

4、绑定(bind)SOCKET地址;

5、监听(listen)SOCKET地址;

6、接受(accept)SOCKET的连接;

具体实例如下:

//发送端

char name[80];
hostent* pHost;
gethostname(name,sizeof(name));//获取本机主机名
pHost = gethostbyname(name);
ip = inet_ntoa(*(struct in_addr*)pHost->h_addr_list[0]);//获取本机IP

int err;

WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2,2);//生成加载的Winsock库的版本
err = WSAStartup(wVersion,&wsaData);//加载套接字库

if(err != 0){return;}

SOCKADDR_IN local_addr;
int addrsize = sizeof(SOCKADDR_IN);

local_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(5150);//绑定端口

if((listen_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{ //创建SOCKET失败   }
else
{      //创建SOCKET成功    }

if(bind(listen_sock,(struct sockaddr*)&local_addr,addrsize))
{//绑定SOCKET失败   }
else
{//绑定SOCKET失败   }

listen(listen_sock,1);//20160426 监听一个客户端



SOCKADDR_IN client_addr;//存储连接的客户端地址

SOCKET Client_Sock;//存储连接的客户端SOCKET

if((Client_Sock=accept(listen_sock,(struct sockaddr*)&client_addr,&addrsize))==INVALID_SOCKET)
{//服务器accept失败   }
else{
{ //服务器accept成功   
//port.Format("%d",int(ntohs(client_addr.sin_port)));
//("已连接来自:"+CString(inet_ntoa(client_addr.sin_addr))+"端口:"+port);
}

//接收数据

char recvMsg[1024] = {0};

int rs = -10;

rs = recv(Client_sock, recvMsg, 1024, 0);

if(rs==-1 || rs==0){//接收数据错误}

else{recvMsg[rs] = ‘\0’}

//发送数据

if(send(Client_sock, sendMsg, strlen(sendMsg),0)==SOCKET_ERROR)
{
    //发送失败
}

客户端:

 

在建立客户端的Socket时,服务其端需要进行:

1、初始化SOCKET运行库;

2、配置通信地址;

3、创建(socket)SOCKET;

4、连接(connect)服务器端的地址;

 

具体实例如下:

WSADATA wsaData;
SOCKADDR_IN server_addr;
WORD wVersion;

wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);

server_addr.sin_addr.S_un.S_addr = inet_addr(ip);//服务端IP
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);//服务端绑定的端口

if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{
printf("Error:创建SOCKET失败!\r\n");
}
else if(connect(sock,(struct sockaddr*)&server_addr,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
printf("Error:连接服务器失败!\r\n");
}
else
{
printf(">成功连接服务器!\r\n");
}

//接收数据

char recvMsg[1024] = {0};

int rs = -10;

rs = recv(sock, recvMsg, 1024, 0);

if(rs==-1 || rs==0){//接收数据错误}

else{recvMsg[rs] = ‘\0’}

//发送数据

if(send(sock, sendMsg, strlen(sendMsg),0)==SOCKET_ERROR)
{
    //发送失败
}

2、UDP方式

UDP的通讯方式不需要提前建立连接即可发送、接收数据。当需要数据传输时,只需要向某地址发送数据即可,

当接收方发现接收缓存区中有数据时,就会把数据读取出来。这种模式数据传输比较快,但可靠型略低,可能会造成丢包。

当采用UDP方式时,并没有严格的服务器、客户端之分;为了方便理解,可以理解为发送方、接收方。

 

服务器端:

在建立服务器端的Socket时,服务其端需要进行:

1、初始化SOCKET运行库;

2、配置通信地址;

3、创建(socket)SOCKET;

4、发送数据(sendto);

具体实例如下:

WSADATA wsaData;
WORD wVersion;

wVersion = MAKEWORD(2,2);
if(WSAStartup(wVersion,&wsaData) != 0)
{
    UpdateStatus("初始化SOCKET失败!");
    exit(1);
}

SOCKET SockUdp;
SOCKADDR_IN serverAddr;
int addrsize = sizeof(SOCKADDR_IN);

if((SockUdp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
{
    UpdateStatus("创建UDP-SOCKET失败!");
    return;
}

//for send
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.S_un.S_addr = inet_addr("接收端IP地址");
serverAddr.sin_port = htons(9000);    // 接收端端口号

//发送数据

int fromlength=sizeof(serverAddr);
sendto(SockUdp, sendMsg, strlen(sendMsg), 0, (struct sockaddr FAR *)&serverAddr, fromlength);

客户端:

在建立客户端的Socket时,服务其端需要进行:

1、初始化SOCKET运行库;

2、配置通信地址;

3、创建(socket)SOCKET;

4、绑定(bind)接收地址;

5、接收数据(recvFrom)

 

具体实例如下:

WSADATA wsaData;
WORD wVersion = MAKEWORD(2,2);
WSAStartup(wVersion,&wsaData);

SOCKET sock;
SOCKADDR_IN recvAddr;    // 接收端(客户端)的地址
SOCKADDR_IN sendAddr;    // 发送端(服务端)的地址,只用于存储

if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==INVALID_SOCKET)
{
    printf("》创建 UDP SOCKET 失败!\r\n");
}
 
int nlen=sizeof(SOCKADDR_IN); 

//用来从网络上的广播地址接收消息
recvAddr.sin_family = AF_INET;
recvAddr.sin_addr.S_un.S_addr = inet_addr("本机接收IP地址");//接收数据端可以以这种方式设置
recvAddr.sin_port = htons(9000); // 本机接收数据的端口号

//bind
if (bind(sock, (SOCKADDR*)&recvAddr, sizeof(recvAddr)) != 0)  
{   
    printf("》bind error:%d\n", err);  
    closesocket(sock);  
    WSACleanup(); 
}

//接收数据

int res = -10;

int addr_len=sizeof(SOCKADDR_IN);

char recvMsg[1024] = {0};

res = recvfrom(sock, recvMsg,1024, 0, (struct sockaddr *)&sendAddr, &addr_len);
if( res == SOCKET_ERROR)
{ 
    UpdateStatus("》未正确接收数据!");
    int err = WSAGetLastError(); 
    break;
}
else if(res > 0)
{//数据接收成功

    //recvMsg[res] = ‘\0’;

}

 

3、备注

无论采取什么方式,都必须包含头文件: Winsock2.h

同时需要加载ws2_32.lib文件:#pragma comment(lib, "ws2_32.lib")

 

在创建SOCKET时。TCP方式的第二个参数为SOCK_STREAM,UDP方式的第二个参数为SOCK_DGRAM.

TCP方式下,在服务器端需要绑定地址,而对于UDP方式来说,只要接收数据,就需要绑定接收地址

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章