什么是socket
  你经常听到人们谈论着 “socket”,或许你还不知道它的确切含义。现在让我告诉你:它是使用 标准Unix 文件描述符 (file descriptor) 和其它程序通讯的方式。什么?你也许听到一些Unix高手(hacker)这样说过:“呀,Unix中的一切就是文件!”那个家伙也许正在说到一个事实:Unix 程序在执行任何形式的 I/O 的时候,程序是在读或者写一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数。但是(注意后面的话),这个文件可能是一个网络连接,FIFO,管道,终端,磁盘上的文件或者什么其它的东西。Unix 中所有的东西就是文件!所以,你想和Internet上别的程序通讯的时候,你将要使用到文件描述符。你必须理解刚才的话。现在你脑海中或许冒出这样的念头:“那么我从哪里得到网络通讯的文件描述符呢?”,这个问题无论如何我都要回答:你利用系统调用 socket(),它返回套接字描述符 (socket descriptor),然后你再通过它来进行send() 和 recv()调用。“但是...”,你可能有很大的疑惑,“如果它是个文件描述符,那么为什 么不用一般调用read()和write()来进行套接字通讯?”简单的答案是:“你可以使用!”。详细的答案是:“你可以,但是使用send()和recv()让你更好的控制数据传输。”存在这样一个情况:在我们的世界上,有很多种套接字。有DARPA Internet 地址 (Internet 套接字),本地节点的路径名 (Unix套接字),CCITT X.25地址 (你可以将X.25 套接字完全忽略)。也许在你的Unix 机器上还有其它的。我们在这里只讲第一种:Internet 套接字。
Internet 套接字的两种类型 :
  什么意思?有两种类型的Internet 套接字?是的。不,我在撒谎。其实还有很多,但是我可不想吓着你。我们这里只讲两种。除了这些, 我打算另外介绍的 "Raw Sockets" 也是非常强大的,很值得查阅。
那么这两种类型是什么呢?一种是"Stream Sockets"(流格式),另外一种是"Datagram Sockets"(数据包格式)。我们以后谈到它们的时候也会用到"SOCK_STREAM" 和 "SOCK_DGRAM"。数据报套接字有时也叫“无连接套接字”(如果你确实要连接的时候可以用connect()。) 流式套接字是可靠的双向通讯的数据流。如果你向套接字按顺序输出“1,2”,那么它们将按顺序“1,2”到达另一边。它们是无错误的传递的,有自己的错误控制,在此不讨论。
    有什么在使用流式套接字?你可能听说过 telnet,不是吗?它就使用流式套接字。你需要你所输入的字符按顺序到达,不是吗?同样,WWW浏览器使用的 HTTP 协议也使用它们来下载页面。实际上,当你通过端口80 telnet 到一个 WWW 站点,然后输入 “GET pagename” 的时候,你也可以得到 HTML 的内容。为什么流式套接字可以达到高质量的数据传输?这是因为它使用了“传输控制协议 (The Transmission Control Protocol)”,也叫 “TCP” (请参考 RFC-793 获得详细资料。)TCP 控制你的数据按顺序到达并且没有错
误。你也许听到 “TCP” 是因为听到过 “TCP/IP”。这里的 IP 是指“Internet 协议”(请参考 RFC-791。) IP 只是处理Internet 路由而已。
    那么数据报套接字呢?为什么它叫无连接呢?为什么它是不可靠的呢?有这样的一些事实:如果你发送一个数据报,它可能会到达,它可能次序颠倒了。如果它到达,那么在这个包的内部是无错误的。数据报也使用 IP 作路由,但是它不使用 TCP。它使用“用户数据报协议 (User Datagram Protocol)”,也叫 “UDP” (请参考 RFC-768。)
    为什么它们是无连接的呢?主要是因为它并不象流式套接字那样维持一个连接。你只要建立一个包,构造一个有目标信息的IP 头,然后发出去。无需连接。它们通常使用于传输包-包信息。简单的应用程序有:tftp, bootp等等。
    你也许会想:“假如数据丢失了这些程序如何正常工作?”我的朋友,每个程序在 UDP 上有自己的协议。例如,tftp 协议每发出的一个被接受到包,收到者必须发回一个包来说“我收到了!” (一个“命令正确应答”也叫“ACK” 包)。如果在一定时间内(例如5秒),发送方没有收到应答,它将重新发送,直到得到 ACK。这一ACK过程在实现SOCK_DGRAM 应用程序的时候非常重要。

简单的发送和接收实现

服务器端接收代码:

 #include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
#include <stdio.h>
#include <memory.h> void main()
{
WSAData wsd;
WSAStartup(MAKEWORD(,),&wsd); SOCKET s =NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch,,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=INADDR_ANY;
ch.sin_port=htons();
int b=bind(s,(struct sockaddr *) &ch,sizeof(ch));
#define QUEUE_SIZE 5
int l=listen(s,QUEUE_SIZE);
printf("正在监听本机的1041端口!\n");
SOCKET sc=accept(s,,);
printf("客户端已经连接到本机的1041端口!\n");
#define BUF_SIZE 4096
int receByt=;
while()
{
char buf[BUF_SIZE];
receByt=recv(sc,buf,BUF_SIZE,);
buf[receByt]='\0';
if(receByt>)
{
printf("接收的消息是:%s\n",buf);
}
else
{
printf("接收消息结束!");
break;
} }
int ic=closesocket(sc);
int is=closesocket(s); }

客户端发送的代码:

 #include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
#include <stdio.h>
#include <memory.h>
#include <string.h> void main()
{
WSAData wsd;
WSAStartup(MAKEWORD(,),&wsd); SOCKET s =NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
struct sockaddr_in ch;
memset(&ch,,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=inet_addr("127.0.0.1");
ch.sin_port=htons(); int c=connect(s,(struct sockaddr *) &ch,sizeof(ch));
printf("已经连接到服务器的1041端口!现在可以向服务器发送消息了!\n");
#define BUF_SIZE 4096
char info[],buf[BUF_SIZE]; while()
{
gets(info);
if(info[]=='\0')
break;
strcpy(buf,info);
int nsend=send(s,buf,strlen(buf),); }
int ic=closesocket(s);
}

程序代码经过了优化,并且整合多线程,把接收和发送放到同一个文件中,使用参数模式调用发送和接收模块。增加了创建SOCKET的创建的时候s句柄(或对象)判断返回值是否为INVALID_SOCKET,以及socket的bind操作的返回值是否为SOCKET_ERROR,其他socket的操作应该也判断SOCKET_ERROR,以保证程序的稳定性,这里只是测试代码就不去写这么多了,剩下的就由你个人发挥。

 #include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <pthread.h> void Receive();
void Send();
void creatThread(); SOCKET s =NULL;
pthread_t t[];
int threadCount=; void main(int argc,char* argv[])
{
printf("本程序制作人学号:713901040041\n");
printf("程序说明:服务器端和客户端为同一个程序,请使用不同的参数运行.\n");
printf("接收程序请使用 r参数;发送程序请使用 s参数。\n");
//printf("len : %d\n", argc);
//printf("count %d\n",argc);
//printf("value: %s\n",argv[1]);
//printf("%d",argv[1][0]=='r'); if(argc<=)
{
printf("please input program arguments ...\n");
exit();
}
if(argc> && argv[][]=='r')
{
printf("run receive ...\n");
Receive();
}
if(argc> && argv[][]=='s')
{
printf("run send ...\n");
Send();
}
} void* receiveWork(void * args)
{
SOCKET sc=accept(s,,);
if(sc==INVALID_SOCKET)
{
printf("sc Error");
}
creatThread(); printf("----------客户端已经连接到本机的%d线程连接!\n",threadCount-);
#define BUF_SIZE 4096
int receByt=;
while()
{
char buf[BUF_SIZE];
receByt=recv(sc,buf,BUF_SIZE,);
buf[receByt]='\0';
if(receByt>)
{
printf("线程接收的消息是:%s\n",buf);
}
else
{
printf("客户端已退出,");
break;
} }
int ic=closesocket(sc);
printf("服务器结束连接!\n");
return NULL;
} void creatThread()
{
pthread_create(&t[threadCount++],NULL,receiveWork,NULL);
} void Receive()
{
WSAData wsd;
WSAStartup(MAKEWORD(,),&wsd);
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s==INVALID_SOCKET)
{
printf("socket created Error");
}
struct sockaddr_in ch;
memset(&ch,,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=INADDR_ANY;
ch.sin_port=htons();
int b=bind(s,(struct sockaddr *) &ch,sizeof(ch));
if(b==SOCKET_ERROR)
{
printf("bind 失败,出错代码是:%d\n",WSAGetLastError());
exit();
}
#define QUEUE_SIZE 5
int l=listen(s,QUEUE_SIZE);
printf("正在监听本机的1041端口!\n"); creatThread(); for(int i=;i<;i++)
{
pthread_join(t[i],NULL);
} int is=closesocket(s);
} void Send()
{
WSAData wsd;
WSAStartup(MAKEWORD(,),&wsd); SOCKET s =NULL;
s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s==INVALID_SOCKET)
{
printf("socket created Error");
}
struct sockaddr_in ch;
memset(&ch,,sizeof(ch));
ch.sin_family=AF_INET;
ch.sin_addr.s_addr=inet_addr("127.0.0.1");
ch.sin_port=htons(); int c=connect(s,(struct sockaddr *) &ch,sizeof(ch));
printf("已经连接到服务器的1041端口!现在可以向服务器发送消息了!\n");
#define BUF_SIZE 4096
char info[],buf[BUF_SIZE]; while()
{
gets(info);
if(info[]=='\0')
break;
strcpy(buf,info);
int nsend=send(s,buf,strlen(buf),);
}
int ic=closesocket(s);
}

原文点击这里

用C语言进行最基本的socket编程的更多相关文章

  1. [转]C语言SOCKET编程指南

    1.介绍 Socket编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等 ...

  2. C语言SOCKET编程指南

    1.介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措? ...

  3. winsock教程- windows下的socket编程(c语言实现)

    winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程     这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...

  4. 多种语言socket编程集锦—win32

    原文 http://www.blogjava.net/huyi2006/articles/263831.html 借此地方整理以下socket编程的多种语言的实现,socket可以跨平台的通信,因此多 ...

  5. Windows下C语言的Socket编程例子(TCP和UDP)

    原文:Windows下C语言的Socket编程例子(TCP和UDP) 刚刚学windows编程,所以想写学习笔记,这是一个简单的Socket程序例子,开发环境是vc6: 首先是TCP server端: ...

  6. <转>Go语言TCP Socket编程

    授权转载: Tony Bai 原文连接: https://tonybai.com/2015/11/17/tcp-programming-in-golang/ Golang的主要 设计目标之一就是面向大 ...

  7. C语言socket编程

    建议先去看一下思路 真的写的很不错呦~ 思路参考博客:https://www.cnblogs.com/renfanzi/p/5713054.html linux c语言socket编程代码(单一服务端 ...

  8. 计算机网络|C语言Socket编程,实现两个程序间的通信

    C语言Socket编程,实现两个程序间的通信 server和client通信流程图 在mooc上找到的,使用Socket客户端client和服务端server通信的流程图

  9. Go语言TCP Socket编程

      Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不可少也是至关重要的一部分.在日常应用中,我们也可以看到Go中的net以及其subdirectories下的 ...

随机推荐

  1. SpringBoot RestFul集成Swagger2

    一.依赖: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swa ...

  2. 进程间通信IPC之--无名管道(pipe)和有名管道(fifo)(转)

     进程间通信IPC之--无名管道(pipe)和有名管道(fifo) 2012-01-17 22:41:20 分类: C/C++ 每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中 ...

  3. 洛谷【P4551】最长异或路径

    浅谈\(Trie\):https://www.cnblogs.com/AKMer/p/10444829.html 题目传送门:https://www.luogu.org/problemnew/show ...

  4. Window下SVN使用总结

    1 地址:http://subversion.apache.org/packages.html#windows 找到windows下的svn客户端工具.选择Win32Svn 进行安装. 一般环境变量会 ...

  5. Android adb push 和 adb pull

    将电脑 D 盘 libreference-ril.so 文件拷贝到安卓设备的 /system/lib 目录下 $ adb remount $ adb root $ adb push D:\libref ...

  6. centos7下安装Anaconda3

    下载anaconda3: wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-4.2.0-Linux-x86_64 ...

  7. laravel 中JWT完整使用详解

    https://laravel-china.org/articles/10885/full-use-of-jwt

  8. [Java.Web] Servlet 的一些细节

    本文来自 传智播客视频PPT 1. 由于客户端是通过 URL 地址访问 web 服务器中的资源,所以 Servlet 程序若想被外界访问,必须把 servlet 程序映射到一个 URL 地址上,这个工 ...

  9. Memory leak by misusing Autofac

    Recently I’ve found out that we can easily cause a memory leaks in our .net application by improper ...

  10. Django模型层

    ORM简介: MVC或者MTV框架中包括一个重要的部分就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工 ...