socket网络编程基础

一.socket编程函数
1.socket函数
原型:int socket(int domain, int type, int protocol);

作用: 创建一个端点并返回一个socket描述符。

参数解析:
domain: 指定一个会话域名,选择一个协议族用于这个会话。包含于<sys/socket.h>中。目前默认格式包括
    AF_UNIX,AF_LOCAL  AF_INET  AF_INET6...
type: 新套接口的类型描述。
    SOCK_STREAM  SOCK_DGRAM  SOCK_SEQQPACKET...
protocol: 通过domain和type已经基本确定了新建的socket具体是什么类型的套接字,最后一步通过protocol来确定socket到底支持的哪个协议(TCP?UDP?)。
    为0,则可以理解为一个通配符也可以理解为一个默认值,就是说我不指定protocol,由内核自己决定使用哪一个protocol。

返回值:成功返回socket描述,失败返回-1.

2.bind函数
原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

作用:当通过socket创建一个描述符后,它就存在一个名字空间,但未给它分配地址空间。bind函数就是将addr地址分配给sockfd.

参数解析:
sockfd:未分配地址空间的socket描述符。
addr:地址指针。
      赋值:
        sockaddr_in addr;

    
    memset(&addr, 0, sizeof(addr));

        addr.sin_family = AF_INET;

        addr.sin_port = htons(m_nPort);

        addr.sin_addr.s_addr = INADDR_ANY;
    INADDR_ANY:表示当主机有多个ip时,客户连接任意ip都可以。
addrlen:地址长度。

返回值:成功返回0,失败返回-1.

3.listen函数
原型:int listen(int sockfd, int backlog);

作用:处理客户端三次握手过程。

参数解析:
sockfd:分配地址空间的socket描述符。
backlog:backlog参数决定了未完成队列和已完成队列中连接数目之和的最大值。
    内核为任何一个给定的监听套接字维护两个队列。
    1)未完成连接队列
      由客户发出并到达服务器,而服务器正在等待完成相应的TCP三路握手的过程。
      这些套接字处于SYN_RCVD状态。    
    2)已完成连接队列
      每个已完成TCP三路握手过程的客户对应其中一项。这些套接字处于ESTABLISHED状态。
    
返回值:成功返回0,失败返回-1.

4.accept函数
原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

作用:从bind的已完成连接队列中获取一个fd及地址信息。如果该队列为空,则进程进入休眠(套接字为阻塞方式)。

参数解析:
sockfd:分配地址空间的socket描述符。
addr:保存接收到客户的地址信息。
addrlen:客户地址长度。

返回值:成功返回客户连接socket描述符,失败返回-1。

listen和accept过程参考文档:
http://blog.csdn.net/ordeder/article/details/21551567

5.connect函数
原型:int connet(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

作用:用于TCP客户来与服务器建立连接。
    客户端调用connect前并不需要非得调用bind函数,因为内核会根据源IP地址,选择一个临时端口作为源端口。
    如果是TCP套接字,调用connect函数将会激发TCP的三路握手过程,而且仅在连接建立成功或出错时才返回。

参数解析:
sockfd:分配地址空间的socket描述符。
servaddr:指向套接字地址结构的指针,包含服务器IP和端口号。
addrlen:套接字地址结构大小。

返回值:成功返回0,错误返回-1.若失败,需要重新创建套接字。

6.recv函数
原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);

作用:将sockfd接收缓冲区的内容copy到buf中。
    recv函数仅仅是copy数据,真正的接收数据是协议来完成的

参数解析:
sockfd:分配地址空间的socket描述符。
buf:保存接收数据。
len:从sockfd内核接收缓冲区中copy数据长度。
flags:一般填0,设置模式。

返回值:大于0表示接收数据字节长度,0表示对方断开连接,-1表示失败。

7.send函数
原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);

作用:将buf中的内容copy到sockfd内核发送缓冲区中。
    send函数仅仅是copy数据,真正的发送数据是协议来完成的

参数解析:
sockfd:分配地址空间的socket描述符。
buf:保存发送数据。
len:将buf数据copy到sockfd内核发送缓冲区中的长度。
flags:一般填0,设置模式。

返回值:返回发送的字节长度。-1表示失败。

send和recv函数处理过程参考文档:
http://www.cnblogs.com/jianqiang2010/archive/2010/08/20/1804598.html

8.setsockopt函数

9.getsockopt函数

10.其他函数
inet_pton, inet_ntop, getsockname, getpeername


二.问题
1.socket阻塞和非阻塞的区别(列全)
  阻塞:当发出一个不能立即完成的套接字调用时,其进程进入休眠状态,等待相应操作完成。
  socket阻塞分为以下4类:
  1)输入操作:read、readv、recv、recvfrom、recvmsg
    对于阻塞的TCP套接字,如果套接字的接收缓冲区中没有数据可读,该进程将被投入休眠,直到有数据到达。
    对于非阻塞套接字,如果接收缓冲区中没有数据可读,相应的调用将立即返回一个EWOULDBLOCK错误。
  2)输出操作:write、writev、send、sendto、sendmsg
    内核将从应用进程的缓冲区copy到该套接字的发送缓冲区。
    对于阻塞套接字,如果其套接字发送缓冲区中没有空间,进程将被投入睡眠,直到有空间为止。
    对于非阻塞的TCP套接字,如果其发送缓冲区中根本没有空间,输出函数调用将立即返回一个EWOULDBLOCK错误。如果有发送缓冲区中有一些空间,
    返回值将是内核能够复制到该缓冲区中的字节数。
  3)接收外来连接:accept
    对于阻塞套接字调用accept函数,当无新连接到达,调用进程将被投入休眠。
    对于非阻塞套接字调用accept函数,当无新连接到达,accept调用将立即返回一个EWOULDBLOCK错误。
  4)发起外出连接:connect
    对于阻塞套接字,连接不上则阻塞(Linux阻塞75s),如果想不阻塞,则可以采用定时器信号的机制处理。
    对非阻塞套接字,连接不上则立即返回,若为0,则表示已经建立连接;若为-1,如果error为EINPROGRESS,则使用select函数监测fd的连接状态。

  fcntl函数设置。

参考文档:
http://blog.csdn.net/pingnanlee/article/details/7770087
http://blog.csdn.net/nphyez/article/details/10268723

2.gdb调试coredump文件时,函数名为????问号
  一些库找不到(/lib/libstdc++.so.6),或者版本不匹配。

3.sleep和阻塞等待的区别

4.epoll模型详细处理过程

5.nginx详解

6.三次握手与四次挥手的过程。
  三次握手:
    1)客户端发送SYN包到服务器,并进入SYN_SEND状态,等待服务器确认。
    2)服务器收到SYN包,并确认。同时自己发送一个SYN包,及ACK+SYN,服务器进入SYN_RECV状态。
    3)客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
    完成三次握手,客户端与服务器开始传送数据。

  四次挥手:
    TCP是全双工通信方式。
    1)发起关闭一端发出FIN,告诉被关闭端,我关闭发送链路,不再发送数据给你,但你可以发送数据给我。
    2)被动关闭一端发出ACK,确认。
    3)被动关闭一端发出FIN,告诉关闭端,我关闭我的发送链路,不再发送数据给你。
    4)发起关闭一端发出ACK。


7.TIME_WAIT与CLOSE_WAIT状态
 CLOSE_WAIT:
  在关闭TCP连接时,
  发起TCP连接关闭的一方称为client,被动关闭的一方称为server。被动关闭的server收到FIN后,但未发出ACK的TCP状态是CLOSE_WAIT。
 TIME_WAIT:
  根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态。
  TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒。
  TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短连接的服务器,
  如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket,
  甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务。

  可以通过设置端口复用或修改TIME_WAIT等待时间的方式,解决TIME_WAIT状态的问题。
 
参考文档:
http://www.cnblogs.com/sunxucool/p/3449068.html
http://www.cnblogs.com/Jessy/p/3535612.html

8.TIME_WAIT状态设置的意义

9.SO_REUSEADDR如何解决TIME_WAIT状态下端口复用的问题?
  设置了SO_REUSEADDR这个标志的socket,在bind端口时,如果这个端口没在使用或者在使用但处于TIME_WAIT状态,可以绑定成功。
  如果正在使用处于非TIME_WAIT状态,则绑定失败。

参考文档:
http://www.cnblogs.com/qq78292959/archive/2013/01/18/2865926.html



9.TCP/IP如何保证数据的准确性和顺序性


10.线程同步(Linux)
  1)互斥锁

  2)信号量

  3)条件变量
    

11.进程间通信



socket错误编码表:
http://blog.chinaunix.net/uid-116213-id-3376727.html

网络编程:
http://blog.csdn.net/weiyuefei/article/category/2821641
http://blog.csdn.net/weiyuefei/article/details/52242778


复习板块:
1.C/C++基本语法
2.TCP/IP协议
3.socket编程
4.线程和进程同步与异步以及如何编程
5.服务器并发处理(epoll)
6.使用了哪些开源库
  jsoncpp, tinyxml, openssl, mongodb





猜你喜欢

转载自blog.csdn.net/u012654882/article/details/60771818