前言
本文内容分两个部分: socket编程基础知识 与 简单实例。
提示:阅读前有一定计算机网络知识的基础
一、基础知识
1.Internet套接字
【介绍】 应用层 与 传输层 的通道,由ip地址 + 端口号 【分类】 流格式(stream sockets) sock_stream: 全双工可靠面向连接的传输,tcp 数据包格式(datagram socket) sock_dgram: 无连接传输,速度更快,udp
2.socket相关结构体
- socket描述符:int类型
注意:网络字节顺序(Network Byte Order)与 本机字节顺序(Host Byte Order) - struct sockaddr:
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
- struct sockaddr_in:与sockaddr等价,常用
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
- struct in_addr:
struct in_addr {
unsigned long s_addr;
};
- 本机转换
n:网络顺序,h:本机顺序,s:short,l:long htons()–“Host to Network Short” htonl()–“Host to Network Long” ntohs()–“Network to Host Short” ntohl()–“Network to Host Long” 注: 本机字节顺序:与cpu架构有关,x86为小端序 网络字节顺序:大端序 - ip地址类型转换
p or a:表达形式(ascii字符串) n:数值形式(二进制数–存在struct in_addr中)
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
printf("%s",inet_ntoa(ina.sin_addr));
int inet_pton(int family, const char *strptr, void *addrptr);
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
3. server&client交互过程
1.socket 函数 : 创建套接字 int socket(int domain, int type, int protocol) domain : PF_INET, PF_INET6 type : SOCK_STREAM, SOCK_DGRAM protocol : IPPROTO_TCP, IPPROTO_UDP
2.bind 函数 : 绑定(ip地址,端口号), 服务端使用 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) sockfd : 服务器socket addr : 服务器地址
3.listen 函数 : 服务端监听socket,等待连接 int listen(int sockfd, int backlog) sockfd : 服务器socket backlog : 排队队列
4.connect 函数 : 客户端发送的连接请求 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockfd : 客户端socket addr : 服务器地址
5.accept函数 : 服务器监听发现请求,接收 int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen) sockfd : 服务器socket addr : 客户端地址 注:服务端socket: 监听socket、连接socket 监听socket:服务器生命周期仅创建一个 连接socket:每次accept返回新套接字
二、简单实例
【server】 注:链接时添加-lws2_32
#include<winsock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char* argv[])
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsdata;
if (WSAStartup(sockVersion, &wsdata) != 0)
{
return 1;
}
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_sock == -1)
{
cout << "error: create server listen_socket" << endl;
return 1;
}
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(8888);
sockAddr.sin_addr.s_addr = INADDR_ANY;
if (bind(listen_sock, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR){
cout << "error: bind" << endl;
return 1;
}
if(listen(listen_sock, 5) == -1)
{
cout << "Error: listen" << endl;
return 1;
}
SOCKET connect_sock;
sockaddr_in client_sin;
char msg[100];
int flag = 0;
int len = sizeof(client_sin);
while (true){
if(!flag)
cout << "listening..." << endl;
connect_sock = accept(listen_sock, (sockaddr*)&client_sin, &len);
if (connect_sock == -1)
{
cout << "error:accept" << endl;
flag = 0;
return 1;
}
if(!flag)
cout << "connected:" << inet_ntoa(client_sin.sin_addr) << endl;
flag = 1;
int num = recv(connect_sock, msg, 100, 0);
if (num > 0)
{
msg[num] = '\0';
cout <<"Client say: "<< msg << endl;
}
string data;
getline(cin, data);
const char * sendData;
sendData = data.c_str();
send(connect_sock, sendData, strlen(sendData), 0);
closesocket(connect_sock);
}
closesocket(listen_sock);
WSACleanup();
return 0;
}
【client】
#include<winsock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int main()
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
return 1;
}
while (true){
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET){
cout << "Socket error" << endl;
return 1;
}
sockaddr_in sock_in;
sock_in.sin_family = AF_INET;
sock_in.sin_port = htons(8888);
sock_in.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(clientSocket, (sockaddr*)&sock_in, sizeof(sock_in) )== SOCKET_ERROR){
cout << "Connect error" << endl;
return 1;
}
string data;
getline(cin, data);
const char * msg;
msg = data.c_str();
send(clientSocket, msg, strlen(msg), 0);
char revdata[100];
int num = recv(clientSocket, revdata, 100, 0);
if (num > 0){
revdata[num] = '\0';
cout <<"Sever say:"<< revdata << endl;
}
closesocket(clientSocket);
}
WSACleanup();
return 0;
}
|