Socket网络程序设计(1)
———— 基于TCP协议的客户-服务器socket实例
1、TCP网络编程架构
2、代码段
- 服务器:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8888 /*侦听端口地址*/
#define BACKLOG 2 /*侦听队列长度*/
int main(int argc, char *argv[])
{
int ss,sc; /*ss为服务器的socket描述符,sc为客户端的socket描述符*/
struct sockaddr_in server_addr; /*服务器地址结构*/
struct sockaddr_in client_addr; /*客户端地址结构*/
int err; /*返回值*/
pid_t pid;
char words[1024]; /*分叉的进行ID*/
/*建立一个流式套接字*/
ss = socket(AF_INET, SOCK_STREAM, 0);
if(ss < 0){ /*出错*/
printf("socket error\n");
return -1;
}
/*设置服务器地址*/
bzero(&server_addr, sizeof(server_addr)); /*清零*/
server_addr.sin_family = AF_INET; /*协议族*/
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/
server_addr.sin_port = htons(PORT); /*服务器端口*/
/*绑定地址结构到套接字描述符*/
err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err < 0){/*出错*/
printf("bind error\n");
return -1;
}
/*设置侦听*/
err = listen(ss, BACKLOG);
if(err < 0){ /*出错*/
printf("listen error\n");
return -1;
}
/*主循环过程*/
for(;;) {
socklen_t addrlen = sizeof(struct sockaddr);
sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
/*接收客户端连接*/
if(sc < 0){ /*出错*/
continue; /*结束本次循环*/
}else{
sprintf(words, "%d login\n", sc);
write(1, words, strlen(words)+1);
}
/*建立一个新的进程处理到来的连接*/
pid = fork(); /*分叉进程*/
if( pid == 0 ){ /*子进程中*/
//process_conn_server(sc); /*处理连接*/
ssize_t size = 0;
char buffer[1024]; /*数据的缓冲区*/
for(;;){ /*循环处理过程*/
size = read(sc, buffer, 1024); /*从套接字中读取数据放到 缓冲区buffer中*/
if(size == 0){ /*没有数据*/
return;
}
write(1, buffer, size); /*写到标准输出*/
sprintf(buffer, "From %d\n", sc);
write(1, buffer, strlen(buffer)+1); /*写到标准输出*/
/*构建响应字符,为接收到客户端字节的数量*/
sprintf(buffer, "I receive %d bytes altogether\n", size);
write(sc, buffer, strlen(buffer)+1);/*发给客户端*/
}
close(ss); /*在子进程中关闭服务器的侦听*/
}else{
//close(sc); /*在父进程中关闭客户端的连接*/
}
}
}
- 客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8888 /*侦听端口地址*/
#define IP "127.0.0.1" /*服务器IP地址*/
int main(int argc, char *argv[])
{
int s; /*s为socket描述符*/
struct sockaddr_in server_addr; /*服务器地址结构*/
s = socket(AF_INET, SOCK_STREAM, 0); /*建立一个流式套接字 */
if(s < 0){ /*出错*/
printf("socket error\n");
return -1;
}
/*设置服务器地址*/
bzero(&server_addr, sizeof(server_addr)); /*清零*/
server_addr.sin_family = AF_INET; /*协议族*/
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/
server_addr.sin_port = htons(PORT); /*服务器端口*/
/*将用户输入的字符串类型的IP地址转为整型*/
inet_pton(AF_INET, IP, &server_addr.sin_addr);
/*连接服务器*/
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
//process_conn_client(s); /*客户端处理过程*/
ssize_t size = 0;
char buffer[1024]; /*数据的缓冲区*/
for(;;){ /*循环处理过程*/
/*从标准输入中读取数据放到缓冲区buffer中*/
size = read(0, buffer, 1024);
if(size > 0){ /*读到数据*/
write(s, buffer, size); /*发送给服务器*/
size = read(s, buffer, 1024); /*从服务器读取数据*/
write(1, buffer, size); /*写到标准输出*/
}
}
close(s); /*关闭连接*/
return 0;
}
- makefile:
all:client server clean #all规则,它依赖于client和server规则
client: tcp_client.o #client规则,生成客户端可执行程序
gcc -o client tcp_client.o
server: tcp_server.o #server规则,生成服务器端可执行程序
gcc -o server tcp_server.o
clean: #清理规则,删除client、server和中间文件
rm -f tcp_process tcp_client tcp_server *.o
3、效果展示
服务器
不同客户端连接,会显示不同id登录,当发送信息时,也会显示是来自哪个客户端。客户端
两个客户端的连接,当发送信息时,会受到服务器的返回,显示收到的字符数
提供给大家源代码参考:
https://github.com/KevinBetterQ/Network-programming/tree/master/TCP-Practice*
版权声明:本文为KevinBetterQ原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。