头文件:
#include <sys/types.h> //定义数据类型
#include <sys/socket.h> //提供套接字接口和数据结构
#include <netinet/in.h> //定义数据结构sockaddr_in
#include <arpa/inet.h> //提供ip地址转换函数</span>
服务器:
//套接字初始化, client_sock:输出参数,用于通信的客户端套接字, prot:端口号, ip_address:ip地址,默认为NULL表示接收任意网络的连接
//成功则返回true, 失败则返回false
bool server_sock_init(int * client_sock, int port, const char *ip_address)
{
int server_sock_fd;
struct sockaddr_in server_sock_address;
int en = 1;
//创建未命名套接字
if((server_sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
cout<<"failed to create server socket."<<endl;
return false;
}
if (setsockopt(server_sock_fd, SOL_SOCKET, SO_REUSEADDR, &en, sizeof (int)) == -1)
cout<<"failed to set reused address."<<endl;
server_sock_address.sin_family = AF_INET;
if(ip_address == NULL)
server_sock_address.sin_addr.s_addr = INADDR_ANY; //允许来自任何网络接口的链接
else
server_sock_address.sin_addr.s_addr = inet_addr(ip_address);
server_sock_address.sin_port = htons (port); //将主机字节序转化为网络字节序,保证端口号正确
memset (&(server_sock_address.sin_zero), '\0', 8); //填充无意义的字节
//命名套接字
if (bind(server_sock_fd, (struct sockaddr *) &server_sock_address, sizeof (struct sockaddr)) == -1){
cout<<"failed to bind server socket."<<endl;
return false;
}
//创建监听队列
if (listen (server_sock_fd, 5) == -1){
cout<<"failed to listen server socket."<<endl;
return false;
}
//等待一个客户端连接
struct sockaddr_in client_address;
socklen_t client_length = sizeof(struct sockaddr_in);
cout<<"waiting connect..."<<endl;
if((*client_sock = accept(server_sock_fd, (struct sockaddr *)&client_address, &client_length)) == -1){
cout<<"failed to accept a connect."<<endl;
return false;
}
cout<<"connected from "<<inet_ntoa(client_address.sin_addr)<<endl;
return true;
}
客户端:
//server_sock->输出参数,用于网络通信的文件描述符
//port->端口号
//ip_address->ip地址
bool client_sock_init(int *server_sock, int prot, const char * ip_address)
{
int len;
struct sockaddr_in server_address;
if((*server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){
cout<<"failed to create server socket."<<endl;
return false;
}
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(ip_address);
server_address.sin_port = htons(prot);
len = sizeof(server_address);
if(connect(*server_sock, (struct sockaddr *)&server_address, len) == -1){
cout<<"failed to connect server"<<endl;
return false;
}
return true;
}
读写套接字封装:
//发送数据, 成功则返回未发送完的字节数, 失败则返回-1
int write_sock(int sock_fd, char *buf, int length)
{
int byte_send;
if((byte_send = write(sock_fd, buf, length)) == -1){
cout<<"error in write sock."<<endl;
return -1;
}
else
return length - byte_send;
}
//接收数据, 返回未接收到的字节数
int read_sock (int sock_fd, char *buf, int length)
{
int byte_read = -1;
char *ptbuf =buf;
int mlength = length;
int count = 0;
do
{
byte_read = read (sock_fd, ptbuf,mlength);
if (byte_read > 0)
{
ptbuf = ptbuf+byte_read;
mlength = mlength-byte_read;
}
else
return -1;
count++;
if(count > 10000)
return -1;
}while(mlength > 0);
return mlength;
}
写好这些函数后,在服务器端,只需要定义一个一个客户端套接字int client_sock; 再用它作为输出参数调用server_sock_init()函数就可以初始化套接字,在server_sock_init()函数中会等待客户端连接。 在客户端程序中,只需要定义一个服务器套接字int server_sock; 在用它作为输出参数调用client_sock_init()函数就可以初始化套接字并连接服务器。如果连接成功,双方就可以使用write_sock()和read_sock()进行通信了。