linux socket编程系统调用栈
Posted 凌特逸轩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux socket编程系统调用栈相关的知识,希望对你有一定的参考价值。
目录
@(linux socket编程实现原理)
一、网络协议参考模型简介
国际标准组织(ISO)制定了OSI模型。这个模型把网络通信的工作分为7层,从上至下为应用层、表示层、会话层、
传输层、网络层、数据链路层、物理层。
而TCP/IP协议将OSI的7层模型简化为4层,从上至下分别为应用层、传输层、网络互连层(网际层)、网络接口层。
TCP/IP协议实际是一个协议族,为网际数据通信提供不同层次的通路。
TCP协议处于传输层,实现了从一个应用程序到另一个应用程序的数据传递。应用程序通过目的IP地址和端口号
来区分接收数据的不同应用程序。
二、SOCKET概述
socket接口是TCP/IP网络的API,它定义了许多函数或例程,程序员可以使用它来开发TCP/IP网络上的应用程序,
要学习Internet上的TCP/IP网络编程,必须理解socket接口。socket接口设计者最先将接口放在UNIX操作系统中。
如果了解UNIX系统的输入输出的话,就很容易理解socket了。网络的socket数据传输是一种特殊的I/O,socket
也是一种文件描述符。
三、SOCKET基本数据结构
struct sockaddr {
/* address family, AF_xxx;一般为AF_INET,代表Internet(TCP/IP)地址族的IPv4协议 */
sa_family_t sa_family;
/* 14 bytes of protocol address;包含了远程计算机的IP地址、端口号和套接字的数目,这些数据是混杂在一起的*/
char sa_data[14];
};
/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
1、TCP通信编程
前面简单介绍了TCP/IP协议,事实上该协议是十分复杂的(要是一个人从头开始研究网络协议的话,这辈子可能
啥也没干就过去了)。要编写一个优秀的网络程序也是十分困难的。服务端与客户端TCP通信的过程大致如下:
服务器端:
1. 首先服务器启动,通过调用socket()建立一个套接字
2. 调用bind()将该套接字和本地网络地址联系在一起
3. 调用listen()使套接字做好侦听的准备,并规定它的请求队列的长度
4. 调用accept()来接收连接
客户端:
1. 通过调用socket()建立一个套接字
2. 调用connect()和服务器建立连接。
3. 连接一旦建立,客户机和服务器之间就可以通过调用read和write函数来发送和接收数据了
4. 最后,待数据传送结束之后,双方调用close()关闭套接字,通信关闭。
2、服务器端实例代码
#include <stdio.h> /* perror */
#include <stdlib.h> /* exit */
#include <sys/types.h> /* WNOHANG */
#include <sys/wait.h> /* waitpid */
#include <string.h> /* memset */
#include "socketwrapper.h" /* socket layer wrapper */
#define true 1
#define false 0
#define MYPORT 12334 /* 监听的端口 */
#define BACKLOG 10 /* listen的请求接收队列长度 */
#define MAXSIZE 100
int main()
{
int numbytes=0;
int sockfd, new_fd; /* 监听端口,数据端口 */
struct sockaddr_in sa; /* 自身的地址信息 */
struct sockaddr_in client_addr; /* 连接对方的地址信息 */
int sin_size;
char buf[MAXSIZE];
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
sa.sin_family = AF_INET;
sa.sin_port = Htons(MYPORT); /* 网络字节顺序 */
sa.sin_addr.s_addr = INADDR_ANY; /* 自动填本机IP */
memset(&(sa.sin_zero),0, 8); /* 其余部分置0 */
if ( Bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
{
perror("bind");
exit(1);
}
if (Listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
new_fd = Accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
if (new_fd == -1)
{
perror("accept");
exit(1);
}
printf("Got connection from %s
", Inet_ntoa(client_addr.sin_addr));
/* 主循环 */
while(1)
{
if ((numbytes=recv(new_fd,buf,MAXSIZE,0))>0)
{
buf[numbytes]=0;
printf("received:%s & length=%d
",buf,numbytes);
if(send(new_fd,buf,strlen(buf), 0) == -1)
perror("send");
}
}
return true;
}
3、客户端实例代码
#include <stdio.h> /* perror */
#include <stdlib.h> /* exit */
#include <sys/types.h> /* WNOHANG */
#include <sys/wait.h> /* waitpid */
#include <string.h> /* memset */
#include "socketwrapper.h" /* socket layer wrapper */
#define true 1
#define false 0
#define PORT 12334 /* Server的端口 */
#define MAXDATASIZE 100 /*一次可以读的最大字节数 */
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he; /* 主机信息 */
struct sockaddr_in server_addr; /* 对方地址信息 */
if (argc != 2)
{
fprintf(stderr,"usage: client hostname
");
exit(1);
}
/* get the host info */
if ((he=Gethostbyname(argv[1])) == NULL)
{
/* 注意:获取DNS信息时,显示出错需要用herror而不是perror */
/* herror 在新的版本中会出现警告,已经建议不要使用了 */
perror("gethostbyname");
exit(1);
}
if ((sockfd=socket(PF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = Htons(PORT); /* short, NBO */
server_addr.sin_addr = *((struct in_addr *)he->h_addr_list[0]);
memset(&(server_addr.sin_zero),0, 8); /* 其余部分设成0 */
if (Connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
while(1)
{
printf("Enter Something:");
scanf("%s",buf);
numbytes=send(sockfd,buf,strlen(buf),0);
numbytes=recv(sockfd,buf,MAXDATASIZE,0);
buf[numbytes]='