socket编程(二)

1.TCP客户/服务器模型

2.回射客户/服务器


3.socket函数

头文件:<sys/socket.h>

功能:创建一个套接字用于通信

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

参数:domain:指定通信协议族(protocol family)

            type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW

            protocol:协议类型

返回值:成功返回非负整数,它与文件描述符类似,我们把它称为套接口描述字,简称套接字。失败返回-1。

4. bind函数

头文件:<sys/socket.h>

功能:绑定一个本地地址到套接字

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

参数: sockfd:socket函数返回的套接字

             addr:要绑定的地址

             addrlen:地址长度

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

5. listen函数

主动套接字:发起连接connect

被动套接字:接受连接accept

头文件:#include <sys/socket.h>

功能:将套接字用于监听进入的连接

原型:int listen(int sockfd, int backlog);

参数:sockfd:socket函数返回的套接字

           backlog:规定内核为此套接字排队的最大连接个数

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

一般来说,listen函数应该在调用socket和bind函数之后,调用函数accept之前调用。

对于给定的监听套接口,内核要维护两个队列:

1.   已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程

2.   已完成连接的队列

6.accept函数

   头文件:<sys/socket.h>

   功能:从已完成连接队列返回第一个连接,如果已完成连接队列为空,则阻塞。

   原型:int accept(intsockfd, struct sockaddr* addr, socklen_t* addrlen);

   参数:sockfd:服务器套接字

               addr:将返回对等方的套接字地址

               addrlen:返回对等方的套接字地址长度

返回值:成功返回非负整数,失败返回-1

7.  connect函数

头文件:<sys/socket.h>

功能:建立一个连接至addr所指定的套接字

原型:int connect(int sockfd, const structsockaddr* addr, socklen_t addrlen);

参数:sockfd:未连接套接字

         addr:要连接的套接字地址

         addrlen:第二个参数addr长度

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

8.示例

echoserver.cpp

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>


#define ERR_EXIT(m) \
    do \
    { \
    	perror(m); \
    	exit(EXIT_FAILURE); \
    }while(0)
    


int main () {
  
	int listenfd;
	if(( listenfd= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  	//if((listenfd= socket(PF_INET, SOCK_STREAM, 0)) <0) 
  		ERR_EXIT("socket");
  	
  	
  	struct sockaddr_in servaddr;
  	memset(&servaddr, 0, sizeof(servaddr));
  	servaddr.sin_family = AF_INET;
  	servaddr.sin_port = htons(5188);
  	//servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  	//inet_aton("127.0.0.1", &servaddr.sin_addr);
  	
  	if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))<0)
  		ERR_EXIT("bind");
  		
  	if(listen(listenfd, SOMAXCONN) < 0)
  		ERR_EXIT("listen");
  	
  	struct sockaddr_in peeraddr;
  	socklen_t peerlen = sizeof(peeraddr);
  	int conn;
  	if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)
  		ERR_EXIT("accept");
  		
  	char recvbuf[1024];
  	while(1) {
  		memset(recvbuf, 0, sizeof(recvbuf));
  		int ret = read(conn, recvbuf, sizeof(recvbuf));
  		fputs(recvbuf, stdout);
  		write(conn, recvbuf, ret);
  	}
	
	close(listenfd);
	close(conn);
  return 0;
}

echoclient.cpp

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>



#define EXIT_FALURE 1

#define ERR_EXIT(m) \
    do \
    { \
    	perror(m); \
    	exit(EXIT_FALURE); \
    }while(0)
    


int main () {
  
	int sock;
	if(( sock= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  		ERR_EXIT("socket");
  	
  	sock = socket(PF_INET, SOCK_STREAM, 0);
  	
  	struct sockaddr_in servaddr;
  	memset(&servaddr, 0, sizeof(servaddr));
  	servaddr.sin_family = AF_INET;
  	servaddr.sin_port = htons(5188);
  	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  	
  	if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
  		ERR_EXIT("connect");
  	
  	
  	char sendbuf[1024] = {0};	
  	char recvbuf[1024] = {0};
  	while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {
  		write(sock, sendbuf, strlen(sendbuf));
                memset(sendbuf, 0, sizeof(sendbuf));
               memset(recvbuf, 0, sizeof(recvbuf));
  		int ret = read(sock, recvbuf, sizeof(recvbuf));
  		fputs(recvbuf, stdout);
  	}
  	
  	close(sock);
  	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值