做项目经查遇到socket(套接字)的地方,业务的地方大部分直接调用接口,读取到内容后再返回给接口就ok了,但学习要深究其原理,因此决定学习下socket相关的内容,该文章参考了下面这位大佬的文章,不做搬运工,写下自己的理解;
https://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html#!comments
linux上通信和通信协议TCP中的三次握手没有直接联系,学习学的三次握手和四次握手释放都是很底层的东西,linux编程提供了socket.h 的头文件,里面有封装好的服务端和客户端的接口,接口类似于下的
extern int socket (int __domain, int __type, int __protocol) __THROW; 创建
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW; 绑定ip 端口
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); 连接
extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); 发送
extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); 接收
extern int listen (int __fd, int __n) __THROW; 监听
extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len); 接收
extern int shutdown (int __fd, int __how) __THROW; 关闭连接
socket.h头文件在linux系统下都有 很多种
root[/usr]%find . | grep socket.h
./include/asm/socket.h
./include/asm-generic/socket.h
./include/linux/caif/caif_socket.h
./include/linux/netfilter/xt_socket.h
./include/linux/socket.h
./include/bits/socket.h
./include/sys/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/arch/x86/include/uapi/asm/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/config/ieee802154/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/config/netfilter/xt/match/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/linux/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/asm-generic/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/caif/caif_socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/netfilter/xt_socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/socket.h
在服务端要用先调用socket、bind、listen后,循环中等待 accpt recv 等
在客户端 依次是socket 、 connect、send 等
下面是我测试的代码
服务端:
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 4096
int main(int argc, char** argv){
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[4096],sendbuff[4096];
int n;
//创建socket服务端 调用socket() 函数
if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);
//调用函数bind() 绑定ip 端口
if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0); }
// 调用listen()函数 准备接受客户端
if( listen(listenfd, 10) == -1){
printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
printf("======waiting for client's request======\n");
while(1){
//调用函数accept() 获取得到的socket包
struct sockaddr* client_addr = NULL;
if( (connfd = accept(listenfd, client_addr, NULL)) == -1){
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
// 调用recv 函数获取内容
n = recv(connfd, buff, MAXLINE, 0);
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
for (int i = 0; i
客户端:
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 4096
int main(int argc, char** argv)
{
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;
if( argc != 2){
printf("usage: ./client \n");
exit(0);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);
if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
printf("inet_pton error for %s\n",argv[1]);
exit(0);
}
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
if (recv(sockfd, recvline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
printf("recv msg from server: %s\n",recvline);
close(sockfd);
exit(0);
}
至于将的协议 其他之类 暂时不熟悉 不表。