日期:2014-05-16  浏览次数:20757 次

求教一些关于socket的系列知识,以及一点内核知识。
1)socket   通讯编程究竟指什么?其本质是什么?和具体的协议(tcp,udp,icmp,ip)有什么关系呢?为什么叫socket(插头)呢?socket_id   代表一个什么东东?应用程序中的SOCKET与内核是怎么交换数据的呢?现在的网卡都是全双工的,用两个进程对一个socket_id实现同时发和收可以吗,就是一个发另一个收?请说述一下,最好能举个例子。
2)通过socket发送数据时,这些数据是被马上发出的吗?还是要放在缓存一会?比如使用数据报发送,也就是UDP协议。
3)操作系统的时间片和CPU的中断响应时间有什么关系?UNIX的时间片是100US,那是不是可以认为用POLL或者SELECT来做定时器,最多只能精确到100US?
谢谢你了。

------解决方案--------------------
1 用两个进程对一个socket_id实现同时发和收可以吗,当然可以的

2 不是,要到系统的缓冲区,然后再由系统发送出去的

------解决方案--------------------
个人理解,不保证正确性

1:
socket是TCP协议栈提供给用户的接口,就像open/read等,属于系统调用。socket_id其实就是一个file descriptor。应用层通过系统调用与内核进行数据交换。
2:
发送方式可以设置,TCP协议栈默认是使用缓存的,你可以设成不使用。
3:
时间片大小是根据进程调度策略来定义的,和CPU中断响应时间没啥关系。
不是
------解决方案--------------------
同意。
补充一下最后一个,答案也是没有关系。详细可以看看kernel/sched.c就明白了。

----------------

i_noname(晚九朝五) ( ) 信誉:100 Blog 加为好友 2007-6-17 18:28:46 得分: 0



个人理解,不保证正确性

1:
socket是TCP协议栈提供给用户的接口,就像open/read等,属于系统调用。socket_id其实就是一个file descriptor。应用层通过系统调用与内核进行数据交换。
2:
发送方式可以设置,TCP协议栈默认是使用缓存的,你可以设成不使用。
3:
时间片大小是根据进程调度策略来定义的,和CPU中断响应时间没啥关系。
不是




------解决方案--------------------

我也理解一下
socket编程实际上就是进程间编程,不仅仅指网络编程.
不管你使用的那种协议,当你发送/接收一个数据包时,实际上时调用的一个系统调用sys_socket(),此调用会根据你
的设置把数据包放入/取出内核缓冲区,由网卡的驱动程序根据情况来把数据转换成电平信号传送出去,你讲的
全双工/半双工一般是指的电平信号的发送/和接收,属于较低层的概念.

------解决方案--------------------
socket不仅可以应用TCP协议,还可以应用UDP协议,只不过tcp是有连接的,udp是无连接的罢了。
至于他们的传输,应该说在我们的程序中就只调用send(),recv(),一类函数而已,我们自己的基本是没有做什么事情的.
------解决方案--------------------
先简单说下 TCP 和 UDP
TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议,当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的.

UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议,这种协议并不能保证我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用TCP 协议的

在linux 套接字编程是通过以下五个关键函数实现的:
socket
int socket(int domain, int type,int protocol)

domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX 和AF_INET 等).
AF_UNIX 只能够用于单一的Unix 系统进程间通信,
AF_INET 是针对Internet 的,因而可以允许在远程 主机之间通信

type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM 等)
SOCK_STREAM表明我们用的是TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流.
SOCK_DGRAM 表明我们用的是UDP 协议,这样只会提供定长的,不可靠,无连接的通信.

protocol:由于我们指定了type,所以这个地方我们一般只要用0 来代替就可以了

成功时返回文件描述符,失败时返回-1,看errno 可知道出错的详细情况.

bind [绑]
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)

sockfd:是由socket 调用返回的文件描述符.

addrlen:是sockaddr 结构的长度.

my_addr:是一个指向sockaddr 的指针. 在 <linux/socket.h> ;中有 sockaddr 的定义
struct sockaddr{
unisgned short as_family;
char sa_data[14];
};
不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.在 <linux/in.h> ;中有sockaddr_in 的定义
struct sockaddr_in{
unsigned short sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
sin_family 一般为AF_INET,
sin_addr 设置为INADDR_ANY 表示可以 和任何的主机通信,
sin_port 是我们要监听的端口号.
sin_zero[8]是用来填充的

bind 将本地的端口同socket 返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket 一样

listen
int listen(int sockfd,int backlog)
sockfd:是bind 后的文件描述符.
backlog:设置请求排队的最大长度.

listen 函数将bind 的文件描述符变为监听套接字.返回的情况和bind 一样.


accept
int accept(int sockfd, struct sockaddr *addr,int *addrlen)
sockfd:是listen 后的文件描述符.