套接字的基本概念套接字函数本地套接字示例:服务器端本地套接字示例,客户端本地套接字示例:运行网络套接字示例:客户端
套接字的基本概念
通信类型: 控制套接字如何传输和处理数据,数据以包的形式传输
连接(connection)类型:确保所有包依序传输,如果丢包,则请求重传数据报(datagram)类型:不保证包的到达顺序,包可能丢失
名空间: 指定套接字地址格式
本地名空间:套接字地址为普通文件名Internet名空间:套接字地址由Internet地址和端口号(用于区分一台主机上的多个套接字)确定
协议: 确定数据如何传输
套接字函数
socket()函数: 创建套接字
原型:int socket(int domain,int type,int protocol);参数:名空间、通信类型和协议名空间:PF_LOCAL(本地)或PF_INET(Internet)通信类型:SOCK_STREAM(连接类型)或SOCK_DGRAM(数据报类型)协议:传递0,让系统自动选择协议(通常为最佳协议)返回值:套接字描述符
close()函数: 释放套接字
原型:int close(int fd);
connect()函数: 创建两个套接字之间的连接
客户发起此系统调用,试图与服务器建立套接字连接原型:int connect(int sockfd,const struct sockaddr* addr,socklen_t addrlen);参数:sockfd 为文件描述符; addr 为指向套接字地址结构体指针(服务器地址);addrlen 为服务器地址字符串的长度返回值:0 连接成功; -1 连接失败
send()函数: 发送数据
原型: ssize_t send(int sockfd,const void* buf,size_t len,int flags);只有在套接字处于连接状态时才可调用
bind()函数: 绑定套接字与其服务器地址
原型:int bind(int sockfd,const struct sockaddr* addr,socklen_t addrlen);
listen()函数: 侦听客户连接
原型:int listen(int sockfd,int backlog);参数:backlog 指定有多少个连接可以进入队列,超出该值的连接将被抛弃
accept()函数: 接受连接,为该连接创建一个新的套接字
原型 int accept(int sockfd,struct sockaddr* addr,socklen_t addrlen);参数: addr 为指向套接字地址结构体(客户地址)的指针返回值:创建一个新的套接字,以接受客户连接,返回值为新的套接字文件描述符原先套接字文件描述符可以继续接受新连接
本地套接字示例:服务器端
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
bool Serve(
int client_socket)
{
while (
true) {
int length;
char* msg;
if(read(client_socket,&length,
sizeof(length)) ==
0)
return true;
msg =
new char[length];
read(client_socket,msg,length);
std::
cout<<msg<<
std::endl;
if(!
strcmp(msg,
"quit")) {
delete[] msg,msg = NULL;
return false;}
else delete[] msg, msg = NULL;
}
}
int main(
int argc,
char*
const argv[])
{
const char*
const socket_name = argv[
1];
ing socket_fd;
struct sockaddr_un name;
bool serving =
true;
socket_fd = socket(PF_LOCAL,SOCK_STREAM,
0);
name.sun_family = AF_LOCAL;
strcpy(name.sun_path,socket_name);
bind(socket_fd,(
struct sockaddr*)&name,SUN_LEN(&name));
listen(socket_fd,
5);
while(serving)
{
struct sockaddr_un client_name;
socklen_t client_name_len;
int client_socket_fd;
client_socket_fd = accept(socket_fd,(
struct sockaddr*)&client_name,&client_name_len);
serving = Serve(client_socket_fd);
close(socket_fd);
}
close(socket_fd);
unlink(socket_name);
return 0;
}
本地套接字示例,客户端
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
void SendMsg(
int socket_fd,
const char* msg)
{
int length =
strlen(msg) +
1;
write(socket_fd,&length,
sizeof(length));
write(socket_fd,msg,length);
}
int main(
int argc,
char const *argv[]) {
const char*
const socket_name = argv[
1];
const char*
const msg = argv[
2];
int socket_fd;
struct sockaddr_un name;
socket_fd = socket(PF_LOCAL,SOCK_STREAM,
0);
name.sun_family = AF_LOCAL;
strcpy(name.sun_path,socket_name);
connect(socket_fd,(
struct sockaddr*)&name,SUN_LEN(&name));
SendMsg(socket_fd,msg);
close(socket_fd);
return 0;
}
本地套接字示例:运行
程序测试运行
编译链接服务端程序和客户端程序进入服务端程序目录,在终端输入:./server/tmp/socket; ./server 为服务器端程序名, /tmp/socket 为本服务器启动后的套接字文件名进入客户端程序目录,在终端中输入:./client/tmp/socket"Hello World!"; ./client 为客户端程序名停止服务器,在客户端输入命令:./client/tmp/socket"quit"
网络套接字示例:客户端
#include <iostream>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
void GetHomepage(
int socket_fd)
{
char buffer[
8192];
sprintf(buffer,
"GET /\n");
write(socket_fd,buffer,
strlen(buffer));
while(
true){
ssize_t count = read(socket_fd,buffer,
8192);
if(count ==
0)
return;
fwrite(buffer,
sizeof(
char),count,stdout);
}
}
int main(
int argc,
char const *argv[])
{
int socket_fd;
struct sockaddr_in name;
struct hostent* hostinfo;
socket_fd = socket(PF_INET,SOCK_STREAM,
0);
name.sin_family = AF_INET;
hostinfo = gethostbname(argv[
1]);
if(hostinfo == NULL)
return 1;
else name.sin_addr = *((
struct in_addr*)hostinfo ->h_addr);
name.sin_port = htons(
80);
if(connect(socket_fd,(
struct in_addr*)&name,
sizeof(
struct sockaddr_in)) == -
1) {
perror(
"Failure to connect the server.");
return 2;
}
GetHomepage(socket_fd);
return 0;
}
“
“`