下面是socket编程的服务器端
先看一个图,1
复制代码
1 #include
2 #include
3 #include
4 #include
5
6 #include
7 #include
8 #include
9
10 #include
11
12 #define MAXLINE 80
13 #define SER_PORT 8000
14
15 int main(void){
16
17 struct sockaddr_in servaddr,cliaddr;
18 socklen_t cliaddr_len;
19
20 int listenfd,connfd;
21 char buf[MAXLINE];
22 char str[INET_ADDRSTRLEN];
23 int i,n;
24 char tt[] = “exit1”; //这里有字符数组和字符指针的区别的坑 具体百度查询
25 char *bb;
26
27 listenfd = socket(AF_INET,SOCK_STREAM,0); //
28 // domain 协议域 AF_INET AF_INET6,AF_LOCAL(AF_UNIX) AF_ROUTE
29 // type socket类型 SOCK_STREAM(流式socket 针对tcp ) SOCK_DGRAM(数据包 针对udp) SOCK_RAW
30 // protocol 协议 tcp协议,udp协议 stcp协议 tipc协议
31
32 bzero(&servaddr,sizeof(servaddr)); //初始化赋值为0
33
34 servaddr.sin_family = AF_INET;
35 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //任何ip //这里是大小端的 转换问题。。可以 百度
36 servaddr.sin_port = htons(SER_PORT); //端口
37
38 bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); //绑定链接的套接字描述符 和 地址和端口
39
40 listen(listenfd,20);
41
42 printf(“Accepting connections … \n “);
43 while(1){
44
45 cliaddr_len = sizeof(cliaddr);
46 connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); //连接的套接字描述符 返回链接的地址 返回地址的缓冲区长度
47
48 //返回 客户端的套接字描述符
49 printf(“connfd:%d------\n”,connfd);
50
51 printf(“received from %s at PORT %d \n”,
52 inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),
53 ntohs(cliaddr.sin_port));
54 while(1){
55 n = read(connfd,buf,MAXLINE); // read(int fd,void *buf, size_t count); 成功返回 读取的字节数 数据保存在buf上 读取客户端的数据
56
57 printf(”%d,”)
58 //printf(“buf:%s-----%d\n”,buf,strcmp(buf,“exit1”));
59 //printf(“tt:%s-----%d\n”,tt,strcmp(tt,“exit1”));
60 for(int i=0;i<5;i++){
61 tt[i] = buf[i];
62 }
63 printf(“tt:%s-----%d\n”,tt,strcmp(tt,“exit1”));
64 if(strcmp(tt,“exit1”) == 0){ //strcmp 对比的就是字符
65 close(connfd);
66 printf(“close:-----\n”);
67 break;
68 }
69
70 for(i=0; i < n; i++){
71 buf[i] = toupper(buf[i]);
72 }
73 write(connfd,buf,n); // // 向客户端写入数据
74 }
75
76 }
77
78 return 0;
79
80 }
81
82 //这个程序有漏洞,如果客户端断线或者关闭,服务器就会死循环。 客户端的标准输入是阻塞的。。。其他都不是阻塞的。
复制代码
客户端
复制代码
1 #include
2 #include
3 #include
4 #include
5
6 #include
7 #include
8 #include
9
10 #include
11
12 #define MAXLINE 80
13 #define SER_PORT 8000
14
15 int main(int argc,char *argv[]){
16
17
18 struct sockaddr_in servaddr;
19 char buf[MAXLINE];
20
21 int sockfd,n;
22 char *str;
23 char tt[5];
24
25 //if(argc != 2){
26 // fputs(“usage: ./client message \n “,stderr);
27 // exit(1);
28 //}
29
30 //str = argv[1];
31
32 sockfd = socket(AF_INET,SOCK_STREAM,0);
33
34 bzero(&servaddr,sizeof(servaddr));
35 servaddr.sin_family = AF_INET;
36 inet_pton(AF_INET,“127.0.0.1”,&servaddr.sin_addr);
37 servaddr.sin_port = htons(SER_PORT);
38
39 if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0){
40 printf(“connet error:%s\n”,strerror(errno));
41 } //链接服务器
42
43 while(1){
44
45 memset(buf,0,MAXLINE);
46 printf(“client connet server …\n”);
47 n = read(STDIN_FILENO,buf,MAXLINE); //从标准输入 读取数据
48 for(int i=0;i<5;i++){
49 tt[i] = buf[i];
50 }
51 if(strcmp(tt,“exit1”) == 0){
52 printf(“exit server connect \n”);
53 close(sockfd);
54 return 0;
55 }
56
57 write(sockfd,buf,n); //把我们的输入,写到服务器
58
59 if(strcmp(tt,“exit1”) == 0){
60 printf(“exit server connect \n”);
61 close(sockfd);
62 return 0;
63 }
64
65 n = read(sockfd,buf,MAXLINE); //从服务器读取数据
66
67
68 printf(“Response from server:\n”);
69 write(STDOUT_FILENO,buf,n); //写到标注输出上
70 printf(”\n”);
71 }
72
73 close(sockfd);
74 return 0;
75
76 }
复制代码
实验结果:
总结:一个socket建立一个连接,必须配合一个connect,对应的服务器端对应一个accept 。不能多次connet,多次是之后会报错,也不能同一个客户端socket多次accept,因为服务器已经有了,accept会阻塞等待其他客户端的socket。