Socket服务器和客户端通信

一、服务器端的搭建Server:

1流程socket()--->struct sockaddr_in; ----->bind()------>listen() ---->accept()----->recv()/send()----->close();

2.编写服务器重点函数用法:

a. socket()

#include<sys/socket.h>

int socket(int family, int type, int protocol );

return: 成功返回非负描述符(也叫套接字描述符,简称sockfd),失败返回-1;

family 是协议族(AF_INET是Ipv4的协议,还有ipv6,unix);type是指明套接字类型(SOCK_STREAM,SOCK_DGRAM,流式套接字,数据报套接字);protocol 一般置0,选择所给定family和type组合的系统默认值.

绑定之前用地址结构填充套接字:

struct sockaddr_in addrSer,addrCli;

addSer.sin_family = AF_INET;

addSer.sin_port = htons(MY_PORT);//其中htons()将主机字节顺序转换成网络字节顺序的短整型,属于大端模式

addSer.sin_addr.s_addr = inet_addr(IP_SER);//其中inet_addr()是将带小数点和十进制数转换成二进制以便计算机读取。

socklen_t len = sizeof(struct sockaddr_in);//返回socklen_t类型的len

inet_addr()头文件:

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

 

b.bind()

 

#include<sys/socket.h>

int bind(int socket, const struct sockaddr *address,socklen_t address_len);

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

第一个参数:套接字描述符,创建的套接字返回值。

第二个参数:const struct sockadr*address: 指向特定于协议的地址结构的指针,若定义的是struct sockaddr_in需要强制类型转换。

第三个参数:返回一个socklen_t类型的该地址结构的长度,(其中socklen_t可以等价short类型,struct sockaddr和struct sockaddr_in的长度都是16字节)。

c.listen()

listen函数使用主动连接套接字为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。TCP务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。

该函数把创建的时的socket<主动套接字>,当调用connect时候发起连接客户端套接字,listen把主动套接字变为被动套接字

#include <sys/types.h>

#include <sys/socket.h>

int listen(int sockfd, int backlog);

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

第一个参数:套接字描述符,创建的套接字返回值。

第二个参数:监听套接字消息队列最大值(5~10)

d.accept()

#include <sys/socket.h>

int accept(int socket, struct sockaddr *restrictaddress, socklen_t *restrict address_len);

return :成功返回非负套接字(既创建了新的套接字,返回一个全新的套接字描述符(已连接套接字描述符)),失败-1;

int sockConn = accept(sockSer,(struct sockaddr*)&addrCli,&len)

第一个参数:监听套接字由socket创建

第二个参数:指向cliaddr结构的指针,指向的是特定协议的地址结构的指针,由于返回类型是标准的地址结构的指 针所以,需要强制类型转换(struct sockaddr*)(注意这里指向的是客户端的地址结构指针)

第三个参数:指向len的指针,地址就是指针。

e.recv()/send()服务器一般先打开,等待客户端的连接,所以一般先接消息再发消息。

recv()

#include <sys/types.h>

#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

第一个参数:是已连接套接字(即新的sockConn套接字描述符)。

第二个参数: buf的地址,由于数组名就是地址所以直接写出地址。

第三个地址: 一般0,默认的普通接受数据模式。

send()

#include <sys/types.h>

#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

第一个参数:是已连接套接字(即新的sockConn套接字描述符)。

第二个参数: buf的地址,由于数组名就是地址所以直接写出地址。

第三个地址: 一般0,默认的普通发送数据模式。

char sendbuf[256];

char recvbuf[256];

while(1)

{

recv(sockConn,recvbuf,256,0);

printf("Cli : %s\n",recvbuf);

printf("Ser : ");

scanf("%d",sendbuf);要发的消息不能加\n;

if(strcmp(sendbuf, "quit") == 0)

break;

sendbuf(sockConn, sendbuf,strlen(sendbuf)+1,0);

}

总结:recv(),send() 函数,要是先接受就要先写recv()函数,,下一行用printf函数输出接收函数的字符串,

要是send()函数,发送函数,先布置好格式,用scanf()函数输入发送的字符串,最后在调用send(即可

发送字符串。

recv();接受函数先接再写,用printf("%s\n",recvbuf)函数加\n输出,可以一句输出结束。

send();发送函数先写再发,用scanf("%s",sendbuf)函数不加\n输入,分多句完成。

 

f.close()

#include <unistd.h>

int close(int fd);

头文件:

1 #include<stdio.h>

2 #include<unistd.h>

3 #include<sys/socket.h>

4 #include<stdlib.h>

5 #include<string.h>

6 #include<netinet/in.h>

7 #include<arpa/inet.h>

8

9 #define MY_PORT 9080

10 #define IP_ADDR "127.0.0.1"

11 #define LISTEN_QUENE_SIZE 5

12 #define MAX_BUFFER_SIZE 256

搭建服务器代码:

1 #include"utitl.h"                                                                                                                                 

2 //Server()

3 int main()

4 {

5 //socket()

6 int sockSer = socket(AF_INET, SOCK_STREAM, 0);

7 if(sockSer == -1)

8 {

9 perror("Ser socket");

10 exit(1);

11 }

12 struct sockaddr_in addrSer,addrCli;

13 addrSer.sin_family = AF_INET;

14 addrSer.sin_port = htons(MY_PORT);

15 addrSer.sin_addr.s_addr = inet_addr(IP_ADDR);

16 //bind()

17 int len = sizeof(struct sockaddr_in);

18 int Bind_Ser = bind(sockSer, (struct sockaddr*)&addrSer, len);

19 if (Bind_Ser == -1)

20 {

21 perror("Ser bind");

22 exit (1);

23 }

24 //listen()

25 int Listen_Ser = listen(sockSer,LISTEN_QUENE_SIZE);

26 if(Listen_Ser == -1)

27 {

28 perror("Ser listen");

29 exit(1);

30 }

31 //accept()

32 int sockConn = accept(sockSer, (struct sockaddr*)&addrCli,&len);

33 if(sockConn == -1)

 

 

 34         {

 35             printf("Server accept client is failuer.\n");

 36             close(sockSer);

 37             exit(1);

 38         }

 39         else

 40         {

 41             printf("Server accept client is ok.\n");

 42         }

 43     char sendbuf[MAX_BUFFER_SIZE];

 44     char recvbuf[MAX_BUFFER_SIZE];

 45    //recv(), send()

 46     while (1)

 47     {

 48         recv(sockConn,recvbuf,MAX_BUFFER_SIZE,0);

 49         printf("Cli : >%s\n",recvbuf);

 50         printf("Ser : >");

 51         scanf("%s",sendbuf);

 52         if(strcmp(sendbuf,"quit") == 0)

 53             break;

 54         send(sockConn,sendbuf,strlen(sendbuf)+1,0);

 55     }

 56     close(sockSer);

 57     return 0;

 58 }                       

1.流程 socket()--->struct sockaddr_in(addrSer)(bind())--->connect()---->send()/recv()---->close();

2.编写客户端函数重点:

注意:客户端可以不绑定套接字,listen()函数是服务器特有函数函数。

connect()创建的第二个参数需要服务器的地址结构,所以要构建服务器的地址结构addrSer,第三个参数求的是地址 结构的长度。

3.connect()

#include <sys/types.h>

#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

第一个参数:是客户端套接字描述符sockCli

第二个参数: 是指向特定的协议地址结构指针&addrSer

第三个参数:返回值为socklen_t的地址结构长度。

return :成功返回0.失败-1

服务器代码:

1 #include"utitl.h"

2 //Client

3 int main()

4 {

5 //socket()

6 int sockCli = socket(AF_INET, SOCK_STREAM, 0);

7 if(sockCli == -1)

8 {

9 perror("Cli socket");

10 exit(1);

11 }

12 struct sockaddr_in addrSer;

13 addrSer.sin_family = AF_INET;

14 addrSer.sin_port = htons(MY_PORT);

15 addrSer.sin_addr.s_addr = inet_addr(IP_ADDR);

16 socklen_t len = sizeof( struct sockaddr );

17 //connect()

18 int sockConn = connect(sockCli, (struct sockaddr *)&addrSer, len);

19 if(sockConn == -1)

20 {

21 printf("Client connect server is failuer .\n");

22 close(sockCli);

23 exit(1);

24 }

25 else

26 {

27 printf("Client connect server is ok.\n");

28

29 }

30 char sendbuf[MAX_BUFFER_SIZE];

31 char recvbuf[MAX_BUFFER_SIZE];

32 // send(), recv();

33 while(1)

 34     {

 35         printf("Cli : >");

 36         scanf("%s",sendbuf);

 37         if(strcmp(sendbuf,"quit") == 0)

 38             break;

 39         send(sockCli,sendbuf,strlen(sendbuf)+1,0);

 40        

 41         recv(sockCli,recvbuf,MAX_BUFFER_SIZE,0);

 42         printf("Ser : >%s\n",recvbuf);

 43     }

 44     close(sockCli);

 45 

 46     return 0;

 47 }                                                                                                                                                 

                  

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值