int socket( int domain, int type, int protocol);
函数socket返回一个套接字对象,是一个整数类型。
参数一:使用什么协议,
AF_INET -- IPv4
AF_INET6 -- IPv6。
参数二:套接字的类型,
SOCK_STREAM -- TCP
SOCK_DGRAM -- UDP
参数三:指明要使用的特殊协议,通常只有流类型和数据报类型的需要特殊协议,一般设置为0
套接字地址:
为了进行网络通信,使用结构体sockadr_in来命名套接字:
// 定义
struct sockaddr_in{
int16_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
char sin_zero[ 8 ];
};
struct in_addr{
unint32_t s_addr;
};
// 初始化
struct sockaddr_in serveraddr;
memset( & serveraddr, 0 , sizeof (serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr( " 127.0.0.1 " );
serveraddr.sin_port = htons(SERVER_PORT);
函数bind
bind提供对套接字进行本地命名的方法,这个函数可以用于client与server套接字进行命名,一般更多用于服务器:
int bind( int sock, struct sockaddr * addr, int addrLen);
err = bind( serversock, ( struct sockaddr * ) & serveraddr, sizeof (serveraddr));
int listen( int sock, int backlog);
函数accept
这个函数可以是server来授予客户端提出的连接,在调用accept之前,必须满足下面三个条件:
`已经创建了server套接字 socket()
`已经这个套接字绑定了一个名字 bind()
`已经在监听server端口 listen()
// desciption
int accept( int sock, struct sockaddr * addr, socklen_t * addrlen);
// prog
int len = sizeof ( struct sockaddr);
ret = accept( serversock, ( struct sockaddr * ) & serveraddr, (socklen_t * ) & len);
if (ret >= 0 )
printf( " succ " );
else
printf( " fail " );
// desciption
int connect( int sock, struct sockaddr * addr, socklen_t addrlen);
// prog
int ret = connect( clientsock, ( struct sockaddr * ) & serveraddr, (socklen_t) sizeof (serveraddr));
if (ret >= 0 )
printf( " succ " );
else
printf( " fail " )
连接套接字输入输出send/recv
原型:
int send( int sock, const void * msg, int len, unsigned int flags);
int recv( int sock, void * buf, int len, unsigned int flags);
int sendto( int sock, const void * msg, int len, unsigned int flags, const struct sockaddr * to, socklen_t tolen);
int recvfrom( int sock, void * buf, int len, unsigned int flags, struct sockaddr * from, socklen_t fromlen);
int getsockopt( int sock, int level, int optname, void * optval, socklen_t * optlen);
int setsockopt( int sock, int level, int optname, const void * optval, socklen_t optlen);
下面两个程序分别为客户端和服务器端,由server监听端口,client申请连接,连接成功后,server分别利用send和write函数向client发送数据,当数据接受成功后,client向server返回成功标识。
server
/* prog server */
#include < stdio.h >
#include < unistd.h >
#include < wait.h >
#include < string .h >
#include < stdlib.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < sys / socket.h >
#include < ctime >
#include < arpa / inet.h >
using namespace std;
#define MAXN_STR 40
/* server的端口号 */
int SERVER_PORT;
/* 随即生成端口号 */
int readport()
{
srand(unsigned(time(NULL)));
SERVER_PORT = 30000 + rand() % 10000 ;
FILE * fout = fopen( " port.in " , " w " );
fprintf(fout, " %d\n " ,SERVER_PORT);
fclose(fout);
return 0 ;
}
int main()
{
int serverfd,connectionfd;
int lenclient,lenserver;
int cnt = 0 ;
/* 定义服务器端和客户端的套接字 */
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
char buff[MAXN_STR + 1 ];
/* server每次随机生成端口号,并且写入port.in文件供client读取 */
readport();
/* 创建一个套接字 & 初始化 */
serverfd = socket(AF_INET, SOCK_STREAM, 0 );
memset( & serveraddr, 0 , sizeof (serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(SERVER_PORT);
lenclient = sizeof (clientaddr);
lenserver = sizeof (serveraddr);
/* 对套接字进行本地命名 */
bind(serverfd, (sockaddr * ) & serveraddr, sizeof (serveraddr));
printf( " Socket has been created!\n " );
printf( " Server port : %d\n " ,SERVER_PORT);
/* 对套接字进行监听 */
listen(serverfd, 5 );
while ( true )
{
printf( " ===== %d =====\n " ,cnt ++ );
printf( " Now listening...\n " );
/* 接受客户端申请的连接 */
connectionfd = accept(serverfd,( struct sockaddr * ) & clientaddr,(socklen_t * ) & lenclient);
/* 如果client成功连接到server, 则执行 */
if (connectionfd >= 0 )
{
printf( " Now the link has been connected.\n " );
/* 从客户端的套接字中提取出IP地址 和其他信息 */
int clientip = clientaddr.sin_addr.s_addr;
printf( " Client ip : %d.%d.%d.%d\n " ,clientip & 255 ,(clientip >> 8 ) & 255 ,
(clientip >> 16 ) & 255 ,(clientip >> 24 ) & 255 );
printf( " Client prot : %d\n " ,ntohs(clientaddr.sin_port));
/* 使用send向client发送信息 */
sprintf(buff, " THE SEND MSG " );
printf( " [SEND] Starting sending [send] msg ...\n " );
send(connectionfd, ( void * )buff, strlen(buff), 0 );
recv(connectionfd, ( void * )buff, MAXN_STR, 0 );
if (strlen(buff) > 0 )
printf( " [SUCC] Sending succeed.\n " );
else
printf( " [FAIL] Sending failed.\n " );
/* 使用write向client发送消息 */
sprintf(buff, " THE WRITE MSG " );
printf( " [SEND] starting sending [write] msg ...\n " );
write(connectionfd,buff, strlen(buff));
recv(connectionfd, ( void * )buff, MAXN_STR, 0 );
if (strlen(buff) > 0 )
printf( " [SUCC] Sending succeed.\n " );
else
printf( " [FAIL] Sending failed.\n " );
/* 关闭此连接 */
close(connectionfd);
printf( " Disconnect the link.\n " );
/* 使用sendto向client发送消息(非连接) */
/*
sprintf(buff, "THE SENDTO MSG");
printf("[SEND] Starting sending [sendto] msg ...\n");
*/
/*
sendto(serverfd, (void*)buff, strlen(buff), 0,
(struct sockaddr*)&clientaddr, sizeof(clientaddr));
*/
}
else
{
/* 与client连接失败 */
printf( " ERROR: Failed while establish the link!\n " );
}
}
close(serverfd);
return 0 ;
}
client
/* prog client */
#include < sys / socket.h >
#include < arpa / inet.h >
#include < sys / stat.h >
#include < sys / types.h >
#include < stdio.h >
#include < string .h >
#include < unistd.h >
#include < time.h >
#include < stdlib.h >
#include < wait.h >
#define MAXN_STR 360
/* server端口号 */
int SERVER_PORT;
int CLIENT_PORT;
/* 读取server端口 并且 随即打开client端口 */
int readport()
{
srand(unsigned(time(NULL)));
FILE * fout = fopen( " port.in " , " r " );
fscanf(fout, " %d " , & SERVER_PORT);
fclose(fout);
CLIENT_PORT = 40000 + rand() % 10000 ;
return 0 ;
}
int main()
{
char buff[MAXN_STR];
char succ[] = " succ " ;
char fld[] = " fail " ;
/* client的套接字 */
int clientfd;
/* server的套接字地址 */
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
/* 读取server端口号 */
readport();
/* 创建client的套接字并且初始化server和client的套接字地址 */
clientfd = socket(AF_INET, SOCK_STREAM, 0 );
memset( & serveraddr, 0 , sizeof (serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVER_PORT);
serveraddr.sin_addr.s_addr = inet_addr( " 127.0.0.1 " );
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(CLIENT_PORT);
clientaddr.sin_addr.s_addr = inet_addr( " 127.0.0.1 " );
/* 绑定client套接字 */
bind(clientfd, ( struct sockaddr * ) & clientaddr, sizeof (clientaddr));
printf( " Socket has been created.\n " );
printf( " Client port : %d\n " ,CLIENT_PORT);
/* 向server请求服务 */
printf( " Now require scv from server ...\n " );
int chk = connect(clientfd, ( struct sockaddr * ) & serveraddr, sizeof (serveraddr));
/* 判断是否连接请求成功 */
if (chk < 0 )
{
printf( " ERROR: Could not connect to the host!\n " );
return 0 ;
}
else
{
/* 连接成功,并且输出server的信息 */
printf( " connection established.\n " );
int serverip = serveraddr.sin_addr.s_addr;
printf( " Server ip : %d.%d.%d.%d\n " ,serverip & 255 ,(serverip >> 8 ) & 255 ,
(serverip >> 16 ) & 255 ,(serverip >> 24 ) & 255 );
printf( " Server port : %d\n " ,ntohs(serveraddr.sin_port));
}
/* 使用recv从server接受数据 */
printf( " Starting RECV msg ...\n " );
int len = recv(clientfd,( void * )buff,MAXN_STR, 0 );
buff[len] = 0 ;
if (len > 0 )
{
/* 如果client接受数据成功,则向server发送成功信号 */
printf( " [RECV] %s\n " ,buff);
printf( " [SUCC] Recviving succeed.\n " );
send(clientfd,( void * )succ,strlen(succ), 0 );
}
else
{
/* 否则,向server发送失败信号 */
printf( " [FAIL] Recviving failed.\n " );
send(clientfd,( void * )fld,strlen(fld), 0 );
}
/* 使用read从server读取数据 */
printf( " Starting READ msg ...\n " );
len = read(clientfd,buff,MAXN_STR);
buff[len] = 0 ;
if (len > 0 )
{
/* 如果client接受数据成功,则向server发送成功信号 */
printf( " [RECV] %s\n " ,buff);
printf( " [SUCC] Recviving succeed.\n " );
send(clientfd,( void * )succ,strlen(succ), 0 );
}
else
{
/* 否则,向server发送失败信号 */
printf( " [FAIL] Recviving failed.\n " );
send(clientfd,( void * )fld,strlen(fld), 0 );
}
/* 断开与server的连接 */
close(clientfd);
printf( " Now the connection has been broken\n " );
/* 使用recvfrom从server接受数据(非链接) */
/*
int serverlen = sizeof(serveraddr);
printf("Starting RECVFROM msg ...\n");
len = recvfrom(clientfd, (void*)buff, MAXN_STR, 0,
(struct sockaddr*)&serveraddr, (socklen_t*)&serverlen);
buff[len] = 0;
if(len > 0)
{
// 如果client接受数据成功,则向server发送成功信号
printf("[RECV] %s\n",buff);
printf("[SUCC] Recviving succeed.\n");
}
else
{
// 否则,向server发送失败信号
printf("[FAIL] Recviving failed.\n");
}
*/
close(clientfd);
return 0 ;
}