基于TCP/UDP的Socket编程

匿名 (未验证) 提交于 2019-12-03 00:30:01

基于TCP(面向连接)的socket编程,分为客户端和服务器端。

服务器端的流程如下:

(1)创建套接字(socket)

----   Create a socket.

(2)将套接字绑定到一个本地地址和端口上(bind)

----   Remove any existing file with the same pathname as that to which we want to bind the socket.

(3)将套接字设为监听模式,准备接收客户端请求(listen)即等待客户端调用connect().

----  Construct an address structure for the server's socket, bind the socket to that address, and mark the socket as a listening socket.

(4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)

----  Execute an infinite loop to handle incoming client requests. Each loop iteration (迭代,反复,重复) performs the following steps:

-- Accept a connection, obtaining a new socket, for the connection.

-- Read all of the data from the connected socket and write it to standard output.

(5)用返回的套接字和客户端进行通信(send/recv)

(6)返回,等待另一个客户请求。

(7)关闭套接字。the server must be terminated manually.

客户端的流程如下:

(1)创建套接字(socket)

(2)向服务器发出连接请求(connect)

(3)和服务器端进行通信(send/recv)

(4)关闭套接字

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听(listen),客户端请求,连接确认。

>> 服务器监听:服务器套接字并不定位具体的客户端套接字,而是出于等待连接的状态,实时监控网络状态。

>> 客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

>> 连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求。

        

常用的系统调用如下:

>> socket() : creating  a socket 

A socket is an abstraction of a communication endpoint. Just as they would use file descriptors to access files, applications use socket descriptors to access sockets. To create a socket, we call the socket() function.

原型:int socket(int domain, int type, int protocol);

返回值: returns file (socket) descriptor if OK, -1 on error.

domain:AF_INET, AF_INET6, AF_UNIX, AF_UNSPEC (address format)

type:SOCK_DGRAM, SOCK_RAW, SOCK_STREAM, SOCK_SEQPACKET

protocol:IPPROTO_IP,  IPPROTO_IPV6,  IPPROTO_TCP, IPPROTO_UDP

The protocol argument is usually zero, to select the default protocol for the given domain and socket type. The default protocol for a SOCK_STREAM socket in the AF_INET communication domain is TCP(Transmission Control Protocol). The default protocol for a SOCK_DGRAM socket in the AF_INET communication domain is UDP(User Datagram Protocol).

NOTE: UDP -- 数据报(datagram),无连接的,no logical connection exist between peers for them to communicate. A datagram is a self-contained(独立的) message. 类似于(analogous)发邮件,你可以发送多封邮件,但是不能保证邮件是否到达和邮件到达的顺序。每一封邮件都包含了接收者的地址。

TCP -- 字节流 A byte stream(SOCK_STREAM), in contrast, 在传输数据之前,需要建立连接,面向连接的通信类似于打电话。点到点的连接里包含了source and destination。

Communication on a socket is bidirectional. We can disable I/O on a socket with the shutdown function.

>> shutdown()   

原型:int shutdown(int sockfd, int how);

返回值: returns 0 if OK, -1 on error.

The shutdown() system call closes one or both channels of the socket sockfd, depending on the value of how, which is specified as one of the following:

how:  SHUT_RD, then reading from the socket is disabled.  SHUT_WR, then we can't use the socket for transmitting data. We can use SHUT_RDWR to disable both data transmission and reception.

shutdown() differs from close() in another important respect: it closes the socket channels regardless of whether there are other file descriptors referring to the socket. For example, sockfd refers to a connected stream socket. If we make the following calls, then the connection remains open, and we can still perform I/O on the connection via the file descriptor fd2:

    fd = dup(sockfd);     close(sockfd);

However, if we make the following sequence of calls, then both channels of the connection are closed, and I/O can no longer be performed via fd2:

    fd2 = dup(sockfd);     shutdown(sockfd,SHUT_RDWR);

Note that shutdown() doesn't close the file descriptor, even if how is specified as SHUT_RDWR. To close the file descriptor, we must additionally call close().

>> bind() : binding a socket to an address    

The bind() system call binds a socket to an address.

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

返回值:returns 0 on success, or -1 on error.

The sockfd argument is a file descriptor obtained from a previous call to socket(). The addr argument is a pointer to a structure specifying the address to which this socket is to be bound. The type of structure passed in this argument depends on the socket domain. The addrlen argument specifies the size of the address structure.

Typically, we bind a server's socket to a well-known address - that is, a fixed address that is known in advance to client applications that need to communicate with that server.

>> listen() : listening for incoming connections    

原型:int listen(int sockfd, int backlog); // returns 0 on success, or -1 on error.

The listen() system call marks the stream socket referred to by the file descriptor sockfd as passive. The socket will subsequently be used to accept connections from other(active) sockets.

The client may call connect() before the server calls accept(). This could happen, for example, because the server is busy handling some other clients. This results in a pending connection, as illustrated in Figure 56-2.

             

The kernel must record some information about each pending connection request so that a subsequent accept() can be processed. The backlog argument allows us to limit the number of such pending connections. Further connection requests block until a pending connection is accepted(via accept()), and thus removed from the queue of pending connections.

>> accept() : accepting a connection   

The accept() system call accepts an incoming connection on the listening stream socket referred to by the file descriptor sockfd. If there are no pending connections when accept() is called, the call blocks until a connection request arrives.

The key point to understand about accept() is that it creates a new socket, and this new socket that is connected to the peer socket that performed the connect(). A file descriptor for the connected socket is returned as the function result of the accept() call. The listening socket(sockfd) remains open, and can be used to accept further connections. A typical server application creates one listening socket, binds it to a well-known address, and then handles all client requests by accepting connections via that socket.

>> send()

原型:int send(int sockfd, const void * msg, int len, int flags);


转载请标明出处:基于TCP/UDP的Socket编程
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!