socket网络编程--基础应用篇

首先我们先介绍一些socket编程的基本API,利用这个API实现一个简单的C-S模型,在这个模型中,服务器接收到客户端的消息后,会将接受到的字符串进行大小写转换,然后发送给客户端,并打印。

1、socket函数--创建一个套接字

1 #include <sys/types.h>          /* See NOTES */
2 #include <sys/socket.h>
3 
4 int socket(int domain, int type, int protocol);

  参数分析:

    domain:指定一个通信域,通常用Ipv4协议,使用 AF_INET

    type:指定流的方式,tcp是基于流的传输,通常传入SOCK_STREAM,udp基于数据报的传输,传入SOCK_DGRM

    protocol:这个参数是用于一个第二选择,我们传入0即可

  return value:

    成功的话,返回一个套接字的文件描述符,失败返回-1.

2、bind函数--将套接字绑定到地址(ip+port)上

1 #include <sys/types.h>          /* See NOTES */
2 #include <sys/socket.h>
3 
4 int bind(int sockfd, const struct sockaddr *addr,
5          socklen_t addrlen);

  参数分析:

    sockfd:套接字文件描述符

    addr:通过创建一个结构体struct sockaddr_in srvaddr,然后强转成定义的sockaddr类型即可

    addrlen:前面创建套接字地址结构体的大小

  返回值:

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

3、listen函数--监听连接,定义最大连接数

1 #include <sys/types.h>          /* See NOTES */
2 #include <sys/socket.h>
3 
4 int listen(int sockfd, int backlog);

  参数分析:

    sockfd:套接字文件描述符

    backlog:最大连接数,SOMAXCONN,值为128

  返回值:

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

4、accept函数--接受一个连接

1 #include <sys/types.h>          /* See NOTES */
2 #include <sys/socket.h>
3 
4 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

  参数分析:

    sockfd:套接字文件描述符

    addr:通过创建一个结构体struct sockaddr_in srvaddr,然后强转成定义的sockaddr类型即可

    addrlen:前面创建套接字地址结构体的大小

  返回值:

    成功返回一个用于通信的文件描述符,失败返回-1

5、accept函数--建立一个连接

1 #include <sys/types.h>          /* See NOTES */
2 #include <sys/socket.h>
3 
4 int connect(int sockfd, const struct sockaddr *addr,
5             socklen_t addrlen);

  参数分析:

    sockfd:套接字文件描述符

    addr:通过创建一个结构体struct sockaddr_in srvaddr,然后强转成定义的sockaddr类型即可

    addrlen:前面创建套接字地址结构体的大小

  返回值:

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

SERVER.CPP

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <sys/types.h>
 4 #include <sys/socket.h>
 5 #include <stdlib.h>
 6 #include <arpa/inet.h>
 7 #include <netinet/in.h>
 8 #include <string.h>
 9 #include <unistd.h>
10 using namespace std;
11 
12 
13 #define ERR_EXIT(m)\
14     do\
15     {\
16         perror(m);\
17         exit(EXIT_FAILURE);\
18     }while(0);
19 
20 int main(int argc, char* argv[]){
21     if(argc < 2){
22         cout << "please add port;" <<endl;
23         exit(-1);
24     }
25     int port = atoi(argv[1]);
26     //创建一个套接字
27     int srvfd = socket(AF_INET, SOCK_STREAM, 0);
28     if(srvfd == -1){
29         ERR_EXIT("socket");
30     }
31     //定义一个结构体并填充
32     struct sockaddr_in srvaddr;
33     srvaddr.sin_family = AF_INET;
34     srvaddr.sin_port = htons(port);
35     srvaddr.sin_addr.s_addr = INADDR_ANY;
36     //将套接字绑定到地址上
37     int ret = bind(srvfd, (const struct sockaddr*)&srvaddr, sizeof(srvaddr));
38     if(ret == -1){
39         ERR_EXIT("bind");
40     }
41     //监听套接字
42     ret = listen(srvfd, SOMAXCONN);
43     if(ret == -1){
44         ERR_EXIT("listen");
45     }
46     
47     struct sockaddr_in sockaddr;
48     socklen_t socklen = sizeof(sockaddr);
49     //定义一个套接字,通常为已经连接的套接字
50     int conn;
51     conn = accept(srvfd, (struct sockaddr*)&sockaddr, &socklen);
52     if(conn == -1){
53         ERR_EXIT("conn");
54     }
55     else{
56         cout << "peer ip addr = " << inet_ntoa(sockaddr.sin_addr) << ", port = " << htons(sockaddr.sin_port) << endl;
57     }
58     //循环获取数据,发送数据
59     char recvbuf[1024] = {0};
60     while(1){
61         memset(recvbuf, 0, 1024);
62         int ret = read(conn, recvbuf, 1024);
63         fputs(recvbuf, stdout);
64         for(int i = 0; i < strlen(recvbuf); i++){
65             if(recvbuf[i] >= 'a' && recvbuf[i] <= 'z'){
66                 recvbuf[i] -= 32;
67             }
68             else if(recvbuf[i] >= 'A' && recvbuf[i] <= 'Z'){
69                 recvbuf[i] += 32;
70             }
71         }
72         write(conn, recvbuf, strlen(recvbuf));
73     }
74     //关闭套接字
75     close(srvfd);
76     close(conn);
77     return 0;
78 }

CLIENT.CPP

 1 #include <iostream>
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <stdio.h>
 5 #include <unistd.h>
 6 #include <netinet/in.h>
 7 #include <arpa/inet.h>
 8 #include <stdlib.h>
 9 #include <string.h>
10 using namespace std;
11 
12 #define ERR_EXIT(m)\
13     do\
14     {\
15         perror(m);\
16         exit(EXIT_FAILURE);\
17     }while(0);
18 
19 int main(int argc, char *argv[])
20 {
21     if(argc < 2){
22         ERR_EXIT("need port");
23     }
24     int port = atoi(argv[1]);
25     //创建一个套接字
26     int cltfd = socket(AF_INET, SOCK_STREAM, 0);
27     if(cltfd == -1){
28         ERR_EXIT("socket");
29     }
30     //定义一个地址结构
31     struct sockaddr_in cltaddr;
32     cltaddr.sin_family = AF_INET;
33     cltaddr.sin_port = htons(port);
34     cltaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
35     //进行连接
36     int ret = connect(cltfd, (const struct sockaddr*)&cltaddr, sizeof(cltaddr));
37     if(ret == -1){
38         ERR_EXIT("connect");
39     }
40     else{
41         cout << "connect success" << endl;
42     }
43     char sendbuf[1024] = {0};
44     char recvbuf[1024] = {0};
45     //从标准输入中读入
46     while(fgets(sendbuf, 1024, stdin) != NULL){
47         write(cltfd, sendbuf, strlen(sendbuf));
48         if(read(cltfd, recvbuf, 1024) > 0){
49             cout << "get info from server" << endl;
50             fputs(recvbuf, stdout);
51         }
52         memset(sendbuf, 0, 1024);
53         memset(recvbuf, 0, 1024);
54     }
55     close(cltfd);
56     return 0;
57 }

猜你喜欢

转载自www.cnblogs.com/zz1314/p/12960406.html
今日推荐