C语言socket编程
建议先去看一下思路
真的写的很不错呦~
思路参考博客:https://www.cnblogs.com/renfanzi/p/5713054.html
linux c语言socket编程代码(单一服务端与客户端) 【此代码有bug,但很方便理解,用于理解使用】:
代码参考博客:https://www.cnblogs.com/xudong-bupt/p/3483059.html
服务端代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 8887
#define QUEUE 20
#define BUFFER_SIZE 1024 int main() {
// 实例化socket对象, 定义sockfd
/* AF_INET 默认为IPv4
* SOCK_STREAM 流式socket, for TCP
* 0 协议, 默认选择合适的协议
* */
int server_sockfd = socket(AF_INET, SOCK_STREAM, ); ///定义sockaddr_in
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(MYPORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 将套接字绑定到地址
// bind,成功返回0,出错返回-1
if (bind(server_sockfd, (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)) == -) {
perror("bind");
exit();
} // 监听
// listen,成功返回0,出错返回-1
if (listen(server_sockfd, QUEUE) == -) {
perror("listen");
exit();
} // 客户端套接字
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr); // 进入阻塞状态,等待客户连接
// 成功返回非负描述字,出错返回-1
int conn = accept(server_sockfd, (struct sockaddr *) &client_addr, &length);
if (conn < ) {
perror("connect");
exit();
}
// 循环
while () {
memset(buffer, , sizeof(buffer));
// 接受消息
int len = recv(conn, buffer, sizeof(buffer), );
printf("len: %d\n", len);
//这里是一直循环的,如果客户端说一句话,然后结束以后,这里一直循环,需要注意 if (strcmp(buffer, "exit\n") == )
break;
fputs(buffer, stdout);
// 发送消息
send(conn, "hehe", , );
}
close(conn);
close(server_sockfd);
return ;
}
客户端代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 8887
#define BUFFER_SIZE 1024 int main()
{
///定义sockfd
int sock_cli = socket(AF_INET,SOCK_STREAM, ); ///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip ///连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
send(sock_cli, sendbuf, strlen(sendbuf),); ///发送
if(strcmp(sendbuf,"exit\n")==)
break;
recv(sock_cli, recvbuf, sizeof(recvbuf),); ///接收
fputs(recvbuf, stdout); memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
} close(sock_cli);
return ;
}
采用C/S架构,Tcp、Ip协议,服务器端使用共享内存的方式,不同客户端连接服务端,实现网络聊天室的功能(多用户)
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //数据类型定义
#include <sys/stat.h> //文件属性
#include <netinet/in.h> //定义数据结构sockaddr_in
#include <sys/socket.h> //提供socket函数和数据结构
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h> //共享内存
#include <time.h>
#include<sys/time.h>
#include <arpa/inet.h> #define PERM S_IRUSR | S_IWUSR //用户读写
#define MYPORT 8080 //通信端口
#define BACKLOG 10 //定义服务器段可以连接的最大客户数
#define MYHOST "192.168.2.137"
#define WELCOME "|---------------Welcome to the chat room!----------------|"//当客户端连接服务端时,向客户端发送此字符串 //将int类型转换成char*类型
void itoa(int i, char *string) {
int mask = ;
while (i / mask >= )
mask *= ;
while (mask > ) {
*string++ = i / mask + '';
i %= mask;
mask /= ;
}
*string = '\0';
} //得到当前系统的时间
void get_cur_time(char *time_str) {
struct timeval now;
gettimeofday(&now, NULL);
strcpy(time_str, ctime(&now.tv_sec));
} //创建共享存储区
int shm_create() {
int shmid;
//shmid = shmget(IPC_PRIVATE, 1024, PERM);
if ((shmid = shmget(IPC_PRIVATE, , PERM)) == -) {
fprintf(stderr, "Create Share Memory Error:%s\n\a", strerror(errno));
exit();
}
return shmid;
} //端口绑定函数。创建套接字,并绑定到指定端口
int bindPort(unsigned short int port) {
int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_STREAM, ); //创建基于流套接字
//bzero(&(my_addr.sin_zero),0);
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET; //IPV4协议族
my_addr.sin_port = htons(port); //转换端口为网络字节序
my_addr.sin_addr.s_addr = inet_addr(MYHOST); if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -) {
perror("fail to bind");
exit();
} printf("bind success!\n");
return sockfd;
} int main(int argc, char *argv[]) {
int sockfd, clientfd; //监听套接字、客户套接字
int sin_size, recvbytes; pid_t pid, ppid; //定义父子进程标记
char *buf, *read_addr, *write_addr, *temp, *time_str; //需要用到的缓冲区
struct sockaddr_in their_addr; //定义地址结构
int shmid; shmid = shm_create(); //创建共享存储区 temp = (char *) malloc();
time_str = (char *) malloc();
sockfd = bindPort(MYPORT); //绑定端口 get_cur_time(time_str);
printf("Time is : %s\n", time_str); if (listen(sockfd, BACKLOG) == -) {
//在指定端口上监听
perror("fail to listen");
exit();
} printf("listen....\n");
while () {
/*
if (listen(sockfd, BACKLOG) == -1)
{
perror("fail to listen");
exit(1);
}
*/
//接受一个客户端的连接请求
if ((clientfd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -) {
perror("fail to accept");
exit();
} //得到客户端的IP地址输出
char address[];
inet_ntop(AF_INET, &their_addr.sin_addr, address, sizeof(address)); printf("accept from %s\n", address);
send(clientfd, WELCOME, strlen(WELCOME), ); //发送问候信息
buf = (char *) malloc(); ppid = fork(); //创建子进程
if (ppid == ) //子进程
{
pid = fork(); //子进程创建子进程
while () {
if (pid > ) {
//buf = (char *)malloc(255);
//父进程用于接收信息
memset(buf, , );
printf("OK\n");
if ((recvbytes = recv(clientfd, buf, , )) <= ) {
perror("fail to recv");
close(clientfd);
raise(SIGKILL);
exit();
}
write_addr = shmat(shmid, , ); //shmat将shmid所代表的全局的共享存储区关联到本进程的进程空间
memset(write_addr, '\0', ); //把接收到的消息存入共享存储区中
strncpy(write_addr, buf, ); //把接收到的消息连接此刻的时间字符串输出到标准输出
get_cur_time(time_str);
strcat(buf, time_str);
printf(" %s\n", buf);
} else if (pid == ) {
//子进程用于发送消息
sleep(); //子进程先等待父进程把接收到的信息存入共享存储区
read_addr = shmat(shmid, , ); //读取共享存储区的内容 //temp存储上次读取过的内容,每次先判断是否已经读取过该消息
if (strcmp(temp, read_addr) != ) {
strcpy(temp, read_addr); //更新temp,表示已经读取过该消息 get_cur_time(time_str);
strcat(read_addr, time_str);
if (send(clientfd, read_addr, strlen(read_addr), ) == -) {
perror("fail to send");
exit();
}
memset(read_addr, '\0', );
strcpy(read_addr, temp);
}
} else
perror("fai to fork");
}
}
}
printf("------------------------------------\n");
free(buf);
close(sockfd);
close(clientfd);
return ;
}
客户端二、客户端三...
#include <stdio.h>
#include <netinet/in.h> //定义数据结构sockaddr_in
#include <sys/socket.h> //定义socket函数以及数据结构
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define MYPORT 8080
#define MYHOST "192.168.2.137" int main(int argc, char *argv[])
{
struct sockaddr_in clientaddr; //定义地址结构
pid_t pid;
int clientfd, sendbytes, recvbytes;
struct hostent *host; //主机信息数据结构
char *buf, *buf_read;
// if (argc < 4)
// {
// printf("wrong usage");
// printf("%s host port name\n", argv[0]);
// exit(1);
// }
// host = gethostbyname(argv[1]);
if ((clientfd = socket(AF_INET, SOCK_STREAM, )) == -)
{
perror("fail to create socket");
exit();
}
bzero(&clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(MYPORT);
clientaddr.sin_addr.s_addr = inet_addr(MYHOST);
//客户端连接服务端
if (connect(clientfd, (struct sockaddr *)&clientaddr, sizeof(struct sockaddr)) == -)
{
perror("fail to connect");
exit();
}
buf = (char *)malloc();
memset(buf, , );
buf_read = (char *)malloc(); if (recv(clientfd, buf, , ) == -)
{
perror("fail to recv");
exit();
}
printf("\n%s\n", buf);
pid = fork();
while ()
{
if (pid > )
{
//父进程发送消息
strcpy(buf, "afsasdf");
strcat(buf, ":");
memset(buf_read, , );
fgets(buf_read, , stdin);
strncat(buf, buf_read, strlen(buf_read) - );
if ((sendbytes = send(clientfd, buf, strlen(buf), )) == -)
{
perror("fail to send");
exit();
}
}
else if (pid == )
{
//子进程接受消息
memset(buf, , );
if (recv(clientfd, buf, , ) <= )
{
perror("fail to recv");
close(clientfd);
raise(SIGSTOP);
exit();
}
printf("%s\n", buf);
}
else
perror("fork error");
}
close(clientfd);
return ;
}
C语言socket编程的更多相关文章
- 计算机网络|C语言Socket编程,实现两个程序间的通信
C语言Socket编程,实现两个程序间的通信 server和client通信流程图 在mooc上找到的,使用Socket客户端client和服务端server通信的流程图
- [转]C语言SOCKET编程指南
1.介绍 Socket编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等 ...
- C语言SOCKET编程指南
1.介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措? ...
- 多种语言socket编程集锦—win32
原文 http://www.blogjava.net/huyi2006/articles/263831.html 借此地方整理以下socket编程的多种语言的实现,socket可以跨平台的通信,因此多 ...
- C语言socket编程--每日签到
前几天写了个python的每日签到,你运行还得借助crontab,很是不爽.....正好前几天看了个关于c编写daemon进程,加上自己那点可怜的socket知识,于是我们重操旧页,C语言版的每日签到 ...
- C语言Socket编程(计算机网络作业)
最近我计算机网络课程要做作业了,没办法跟着老师一步一步的写C语言的代码,使用的计算就是Socket通信发送消息:代码实现的功能很简单,客户端向服务器端发送消息,服务器端接收客户端发来的消息,并且输出显 ...
- C语言socket编程——linux环境
先写一个服务器端的监听程序,功能室从客户端读取字符,接收到后告知客户端“I got your message: ”+收到的消息:server.c #include <stdio.h> #i ...
- C语言socket编程----实现UDP通信
TCP/IP协议叫做传输控制/网际协议,又叫做网络通信协议.实际上,它包括上百个功能的协议. 套接字(socket):在网络中用来描述计算机中不同程序与其他计算程序的通信方式. 套接字分为三类; 流式 ...
- C语言socket编程----struct sockaddr 和struct sockaddr_in介绍和初始化
sockaddr结构体 struct sockaddr{ sa_family_t sa_family; //地址族,最常用的是"AF_INET"(IPV4)和"AF_ ...
随机推荐
- fetch添加超时时间
fetch添加超时时间 其实为fetch添加超时时间很简单,需要用到Promise.race()方法. Promise.race() 方法将多个Promise包装成一个新的Promise实例. var ...
- [HNOI/AHOI2018]道路
Description: W 国的交通呈一棵树的形状.W 国一共有\(n - 1\)个城市和\(n\)个乡村,其中城市从\(1\)到\(n - 1\) 编号,乡村从\(1\)到\(n\)编号,且\(1 ...
- Mac + OpenCV3.3.0 + PyCharm (非常简单的配置过程)
最近要用python来写opencv,主要是需要学习计算机视觉和机器学习.看了网上的配置过程,愣是把一件简单的事搞复杂了. 话不多说,配环境走起! 打开PyCharm,找到Preferences 尝试 ...
- JS_高程3.基本概念(5)语句
1.if语句 2.do-while语句:后测循环语句,循环体内的代码至少执行一次. 3.while语句:前测循环语句. 4.for语句:前测循环语句. 注意:在ECMAScript中不存在块级作用域, ...
- 【搜索】WAR大佬的SET @upcexam6201
时间限制: 1 Sec 内存限制: 128 MB 题目描述 WAR大佬认为一个包含重复元素的集合认为是优美的,当且仅当集合中的元素的和等于他们的积. 求包含n个元素的优美的集合的个数. WAR大佬当然 ...
- delphi TTBXToolBar 增加外部控件
这样可以引用外部控件,还是比较方便
- /debug/requests is already registered. You may have two independent copies of golang.org/x/net/trace in your binary, trying to maintain separate state. This may involve a vendored copy of golang.org/x
找到问题就很好解决了,直接百度 go依赖管理-govendor go get -u github.com/kardianos/govendor 先获取这个,然后将govendor.exe放入path ...
- rvs产生服从指定分布的随机数 pdf概率密度函数 cdf累计分布函数 ppf 分位点函数
统计工作中几个常用用法在python统计函数库scipy.stats的使用范例. 正态分布以正态分布的常见需求为例了解scipy.stats的基本使用方法. 1.生成服从指定分布的随机数 norm.r ...
- RbbitMQ消息队列及python实现
1.简介 RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的 ...
- Activity class {com.../com....MainActivity} does not exist.
报错信息如上图所示,解决步骤: 1. 首先是检查这个MainActivity.java是不是真的存在,且包名和路径无误: 2. 如果文件存在,且包名和路径没有问题,那么就打开你项目所在的/androi ...