socket概念
- socket又称“套接字”,是计算机网络中进程间通信数据通道的一个端点,或称之为句柄。IP地址+端口号就可以唯一确定一个socket。
- TCP/IP协议族包括传输层(TCP/UDP),网络层(ICMP/IP/IGMP),链路层(ARP/RARP)。应用层通常使用socket地址,即IP地址+端口号来确定通信的对端。而socket正是TCP/IP协议族与应用层之间的接口层,可以说对上层提供了TCP/IP协议族的一种封装,无需关心更底层的实现。
- 应用上通常使用一些更高层的协议库来编程,socket更多归类于底层驱动编程。不过熟悉socket总归是有好处的。
套接字地址结构
socket基本TCP API
connect函数
bind函数
listen函数
accept函数
close函数
- close一个TCP套接字默认行为是把socket标记为关闭后返回。但触发了四次挥手过程
int close(int sockfd);
传送数据
- 通常需要一个缓冲区,之后使用recv、send函数接收发送
- read、write在*nix系统上也可以
int recv(int sockfd, void *buf, size_t len, int flags);
int send(int sockfd, const void *buf, size_t len, int flags);
TCP通信客户端与服务器端
客户端流程
- 使用connect连接服务器之后就可以开始传输数据
服务器端流程
- 需要首先绑定网络接口(bind),之后进入监听状态(listen),最后从队列中取出一个已经连接的套接字,即获得新连接(accept),之后可以开始传输数据
源代码如下:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdio.h>
int main(){
struct sockaddr_in local;
int s;
int sl;
int rc;
char buf[1000];
local.sin_family = AF_INET;
local.sin_port = htons(7500);
local.sin_addr.s_addr = htonl(INADDR_ANY);
s = socket(AF_INET, SOCK_STREAM, 0);
if ( s < 0){
perror("socket call failed");
exit(1);
}
rc = bind(s, (struct sockaddr *) &local, sizeof(local));
if ( rc < 0){
perror("bind call failed");
exit(1);
}
rc = listen(s, 5);
if ( rc < 0){
perror("listen call failed");
exit(1);
}
sl = accept(s, NULL, NULL);
if ( sl < 0){
perror("accept call failed");
exit(1);
}
rc = recv(sl, buf, 10, 0);
if ( rc < 0){
perror("recv call failed");
exit(1);
}
printf("%s\n", buf);
rc = send(sl, "good", 10, 0);
if ( rc < 0){
perror("send call failed");
exit(1);
}
exit(0);
}
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
int main(){
struct sockaddr_in peer;
int s;
int rc;
char buf[100];
peer.sin_family = AF_INET;
peer.sin_port = htons(7500);
peer.sin_addr.s_addr = inet_addr("127.0.0.1");
s = socket(AF_INET, SOCK_STREAM, 0);
if ( s < 0 ){
perror("socket call failed");
exit(1);
}
rc = connect(s, (struct sockaddr *) &peer, sizeof(peer));
if (rc){
perror("connect call failed");
exit(1);
}
rc = send(s, "hello", 10, 0);
if (rc <= 0)
{
perror("send call failed");
exit(1);
}
rc = recv(s, buf, 10, 0);
if (rc <= 0){
perror("recv call failed");
}
else
printf("%s\n", buf);
exit(0);
}