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 ;
}
上一篇:为什么还坚持.NET? 找一门适合自己的语言去做编程


下一篇:Go语言 并发编程